Authentication
Dracory ships a complete session-based authentication system backed by the
userstore and sessionstore packages. Auth controllers live in
internal/controllers/auth/ and are mounted by
internal/controllers/auth/routes.go.
Login Methods
Enabled login mechanisms are selected at runtime with the
AUTH_LOGIN_METHODS environment variable — a comma-separated (or JSON array) list.
The first entry is the primary method rendered at /auth/login;
each additional method is mounted at its own /auth/<method>-login path and is
offered as an alternative on the login page. The deprecated singular
AUTH_LOGIN_METHOD is still honoured as a fallback.
Supported methods:
otp(default) – in-house email one-time-password login.magiclink– in-house email magic-link login.password– in-house email/password login.authknight– delegates authentication to the external AuthKnight service.
Auth Routes
| Path | Mounted When |
|---|---|
/auth/login |
Always — serves the primary login method |
/auth/otp-login, /auth/magiclink-login, /auth/password-login, /auth/authknight-login |
When the method is enabled but is not primary |
/auth/magiclink-callback |
When magiclink is enabled |
/auth/authknight-callback |
When authknight is enabled |
/auth/forgot-password, /auth/password-reset |
When password is among the enabled methods |
/auth/register |
When AUTH_REGISTRATION_ENABLED=yes |
/auth/logout |
Always |
Registration & Email Allowlist
-
AUTH_REGISTRATION_ENABLED– set tonoto disable the public registration page (defaultyes). -
AUTH_EMAILS_ALLOWED_ACCESS– optional comma-separated allowlist of email domains/addresses. When empty, all emails are allowed. Enforcement is consolidated ininternal/rules/auth(EmailAllowedRule).
When password auth is enabled, the register page is the public sign-up form (email + password) that logs the user in. Otherwise it is the post-authentication profile completion form.
CSRF Protection
AUTH_CSRF_SECRET signs CSRF tokens. It is required in production and staging —
configuration loading fails if missing. In other environments a random secret is generated and a
warning is logged. See the
Environment guide for details.
Rate Limiting
Sensitive auth endpoints are rate-limited to 5 requests per minute per IP
(RateLimitByIPMiddleware(5, 60)) to blunt brute-force attempts. Registration routes
allow 10 requests per minute. Logout is deliberately unthrottled.
User Roles
Roles are stored in the userstore role and user_role tables (enabled via
RolesEnabled in internal/config/store_builders.go). A migration creates
the tables, seeds four default roles — administrator, manager,
superuser, user — and backfills assignments from the legacy
role column.
Helper functions in internal/helpers/user_roles.go:
UserActiveRoleHandles(ctx, app, userID)– map of the user's active role handles.UserHasActiveRole(ctx, app, user, handle)– single-role check.UserHasAnyActiveRole(ctx, app, user, handles...)– any-of check.UserActiveRoleAssign(ctx, app, userID, handle)– assign a role to a user.
New users created via shared.SessionLogin are automatically assigned the
user role.
Sessions
Successful logins flow through internal/controllers/auth/shared.SessionLogin, which
creates the session record and sets the auth cookie. Cookie Secure flags are
environment-aware: relaxed in development, enforced under TLS in production. Session expiry is
maintained by a background goroutine started with the server.