Authentication
qnop supports local accounts and external identity providers side by side. Both end at the same place: a signed access token plus a refresh cookie.
Local accounts
Section titled “Local accounts”Self-registration with e-mail verification, password reset, and an administrator-initiated reset are all built in. Whether users may register themselves — and which role they get when they do — is set in Administration → Settings, not in the environment.
Local accounts need working SMTP for verification and reset mail. SMTP is also configured in the admin area.
Single sign-on
Section titled “Single sign-on”Providers are registered at runtime under Administration → OIDC providers
and stored in the database rather than in configuration files. Five types are
supported — OIDC for any standards-compliant provider (Keycloak, Entra ID,
Auth0 and the rest are configured as generic OIDC through their discovery
document), plus GOOGLE, GITHUB, FACEBOOK and a generic OAUTH2 type.
Client secrets are encrypted at rest with QNOP_AUTH_ENCRYPTION_KEY, which is
what makes rotating that key destructive — see
Configuration.
Two behaviours are worth knowing before you enable a provider: an SSO login
bypasses the self-registration setting, and every SSO user is provisioned as
MEMBER with no linking to an existing account of the same e-mail address.
Setup walkthroughs for each provider, the callback-URL mechanics, the SSRF guard and the failure modes are covered in OIDC / OAuth 2.0 providers.
Sessions
Section titled “Sessions”An access token is a short-lived JWT sent as a bearer token. Alongside it, a refresh token is issued in an HttpOnly cookie and rotates on use, so a stolen refresh token is usable at most once before the rotation is detected.
The cookie is marked Secure by default. A browser will therefore not send it
over plain HTTP — which is a good default and the reason an HTTP-only
deployment behaves as if login never sticks. Terminate TLS.
Rate limiting
Section titled “Rate limiting”The authentication endpoints are individually rate limited — login, refresh, password change, registration and forgot-password each have their own budget, because they have different abuse profiles.
Every user holds exactly one global role:
| Role | What it grants |
|---|---|
ADMIN | the administration area, the actuator endpoints, and the audit trail |
MEMBER | the default — ordinary reviewing; access to individual documents is decided per resource by ownership and participation |
AUDITOR | MEMBER, plus organisation-wide read access to the audit trail |
Roles do not imply one another: ADMIN does not inherit AUDITOR, both are
granted the audit surface explicitly.
Teams add a second, independent axis with LEAD and MEMBER. A team lead
manages membership; the last lead of a team cannot be removed, so no team is
ever left without one.