Skip to content

Authentication ​

Authentication is provided by the official Users plugin (@luna-park/plugin-users). It adds accounts, sessions, roles and permissions, and OAuth sign-in, without writing auth code. The same logic runs in the editor preview and in the exported app.

Install the plugin ​

  1. Open Libraries > Plugins > Install plugins.
  2. Search for Users and install it.

The plugin creates:

  • a Users table and a Sessions table;
  • a User Store holding the connected user in the frontend;
  • a default admin account (login admin, password admin).

Default account

The default admin is only there to get you started. Delete it or change its password before going live.

Settings ​

The plugin adds a button to the top bar with two tabs:

  • General: how users are identified (username or email), the password policy (minimum length, required characters), and the roles and permissions grid.
  • OAuth2: the sign-in providers (see below).

Sign up, log in, log out ​

In a page's logic:

  • user/connect logs in, signs up, or both (login, signup, both) with a login and a password. It outputs the user and throws an error on failure: wrap it in a Try node to show a message.
  • user/disconnect logs out from this device (logout) or from every device (all).
  • user/current gives the connected user and whether someone is connected.
  • user/check-password checks a password against the policy, to give feedback on a sign-up form.

Sessions are stored in signed, httpOnly cookies, one per device.

Protect routes ​

Every backend route receives the connected user as the user input (id, login, roles). Visitors who are not logged in get the anonymous role.

Add a guard in the Guards section of the route's Inspector:

GuardEffect
AuthenticatedOnly logged-in users can call the route (otherwise 401).
PermissionOnly users whose roles grant the chosen permission can call it (401 if anonymous, 403 otherwise).

Routes without guards stay public.

Roles and permissions ​

Define roles and permissions in the General settings, then check them in backend logic:

NodeDescription
roles/has-permissionChecks if a user has a permission.
roles/assert-permissionStops with an error if a user lacks a permission.
roles/set-rolesReplaces a user's roles.

Passwords and sessions ​

Backend nodes:

NodeDescription
user/change-passwordChanges the connected user's password and logs out their other devices.
user/request-password-resetCreates a one-hour, single-use reset token. Send it to the user yourself (for example with the Mail plugin).
user/reset-passwordSets a new password from a reset token.
user/list-sessions / user/revoke-sessionLists or closes the connected user's sessions.
user/connect-by-id / user/disconnect-by-idConnects as, or disconnects, any user (magic links, admin tools). Protect the route with a guard.
user/deleteDeletes a user and their sessions.
hash/hash-argon2 / hash/verify-argon2Hashes a string with Argon2id, or checks it.

OAuth sign-in ​

In the OAuth2 settings, click Add a provider and pick a preset: Google, Discord, GitHub, Microsoft, or GitLab (or any OAuth2 provider). A guide links to the provider's console and gives the redirect URIs to register. Paste the client ID and secret, with separate development and production values.

In the frontend:

  • oauth/connect opens the provider's sign-in popup, then connects the user;
  • oauth/link links a provider account to the connected user.

In production, register this redirect URI with the provider:

https://<your-domain>/api/_users/oauth/callback

Secrets

Client secrets are not written in the code: each one goes to the exported app's .env file as USERS_OAUTH_SECRET_<PROVIDER_ID>.