Authentik (SSO)
Users sign in with Authentik over OIDC (Authorization Code Flow with PKCE). MFA, password rules, account recovery, and the login flow are managed in Authentik. This application manages users, the global administrator flag, browser sessions, and the audit log. Permissions inside a Project are set in this application.
Permissions are decided in two levels.
| Level | Decided by | Where to change |
|---|---|---|
| Can sign in / is a global administrator | Authentik groups and a mapping in the API server's environment | Group membership in Authentik and .env |
| Project role (Viewer / Editor / Admin) | The stronger of a direct grant and a group grant. In a Public Project, everyone who can sign in is an Editor | Project settings |
1. Register in Authentik
Create an application and an OAuth2/OpenID provider in Authentik. Replace https://tracking.example.com below with the actual HTTPS URL of this application (MMT_PUBLIC_URL).
- In the Authentik admin interface, open Applications → Providers → Create and create an OAuth2/OpenID Provider.
- Set the following values.
| Field | Value |
|---|---|
| Client type | Confidential |
| Redirect URIs | https://tracking.example.com/api/auth/callback (exact match) |
| Scopes | The openid, profile, email, and offline_access mappings |
| Back-channel logout URI | https://tracking.example.com/api/auth/oidc/backchannel-logout |
- Create an application under Applications → Create and select the provider. Use
ml-trackingas the slug in this example. - Note the provider's client ID and client secret. Put the client secret only in the API server's
.env.
The issuer URL is per application. With the slug ml-tracking it is https://sso.example.com/application/o/ml-tracking/.
Scopes and groups
Both the ID token and UserInfo must contain these claims:
emailandemail_verified(logins whereemail_verifiedis not true are refused)name(display name)groups(an array of group names)
If UserInfo has no groups, the periodic recheck after login decides that the user is in no group, and everyone's session ends. Check that the provider's scope mappings emit groups.
offline_access (Authentik's built-in "authentik default OAuth Mapping: OpenID 'offline_access'") makes Authentik issue refresh tokens. Without it the application still works, but users must sign in again each time Authentik's access token expires (the provider's Access token validity, 5 minutes by default).
For a seven-day login, edit the Provider and add that mapping under Advanced protocol settings → Scopes. Set Refresh Token Validity to days=7 or longer; an existing days=30 setting can stay as it is. Access Token Validity can remain minutes=5 because the application refreshes access tokens.
2. Configure the API server
Put the following in the API server's .env. HTTPS is required in production. Use hybrid while introducing SSO so that a local administrator remains for emergencies ("Move to SSO" in Authentication).
NODE_ENV=production
AUTH_MODE=hybrid
AUTH_SESSION_IDLE_SECONDS=604800
AUTH_SESSION_ABSOLUTE_SECONDS=604800
MMT_PUBLIC_URL=https://tracking.example.com
MMT_WEB_ORIGIN=https://tracking.example.com
OIDC_ISSUER_URL=https://sso.example.com/application/o/ml-tracking/
OIDC_CLIENT_ID=<provider client ID>
OIDC_CLIENT_SECRET=<provider client secret>
OIDC_LABEL=Authentik
OIDC_SCOPES=openid profile email offline_access
OIDC_ALLOWED_GROUPS=mmt-users,mmt-admins
OIDC_ROLE_MAPPING_JSON={"mmt-admins":"admin","mmt-users":"user"}
OIDC_DEFAULT_ROLE=user
OIDC_AUTO_LINK_VERIFIED_EMAIL=false
MMT_SESSION_ENCRYPTION_KEY=<value generated by the command below>
OIDC_RECHECK_SECONDS=60
OIDC_TOKEN_SYNC_MAX_AGE_SECONDS=604800MMT_SESSION_ENCRYPTION_KEY encrypts the Authentik tokens stored with sessions. Generate it in a terminal and write it only in .env. Use a value different from the storage key (MMT_STORAGE_SECRET_KEY).
openssl rand -base64 32Restart the API after changing the settings. Each variable is listed under "Authentication and SSO" in Environment variables.
These settings keep a login for seven days, including inactivity. Update an existing .env too: changing examples or defaults does not replace values already set there. Sign in once after applying the settings to obtain a refresh token.
Allowed groups and the administrator group
OIDC_ALLOWED_GROUPS: groups allowed to sign in (comma-separated). Required inoidcandhybrid; the API does not start if it is empty. People in none of these groups cannot sign in, and no user is created for them.OIDC_ROLE_MAPPING_JSON: a group → global role mapping. The roles areadmin(global administrator) anduser(sign-in only). Any other value is a startup error. Without it, no one who signs in through SSO is a global administrator.OIDC_DEFAULT_ROLE: the role of allowed users who match no group in the mapping. Defaultuser.
A user in several groups gets the stronger role (admin). Include the groups in the mapping in OIDC_ALLOWED_GROUPS too. People whose groups are all outside the allowed list cannot sign in, whatever the mapping says.
| Authentik groups (example) | In OIDC_ALLOWED_GROUPS | Mapped role | Result |
|---|---|---|---|
mmt-admins | Yes | admin | Can sign in and is a global administrator |
mmt-users | Yes | user | Can sign in and work in Public Projects as an Editor. Other roles are granted separately |
Only mmt-proj-asr-editors | No | — | Cannot sign in |
mmt-users and mmt-proj-asr-editors | mmt-users is | user | Can sign in, and grants to mmt-proj-asr-editors apply |
Check
- Open this application in a browser and check that the login screen shows the Authentik button (the value of
OIDC_LABEL). - Have someone in
mmt-adminssign in with SSO, open Global settings from the user menu, and check that the Administration group (Projects, Users, and so on) appears in the sidebar. - Have someone only in
mmt-userssign in, open Global settings from the user menu, and check that the sidebar shows the Global settings group (Account, Computers) but not the Administration group. - Check that someone in neither group is refused. The reason is recorded in the audit log as
auth.oidc.denied("Cannot sign in with SSO" in Troubleshooting).
What is synchronized at each login
- A user is created at the first SSO login. There is no self sign-up screen.
- The global administrator flag and the user's groups are synchronized at every login. If you change the flag on the screen, the next login restores Authentik's state. Change Authentik groups for a permanent change.
- The display name and email are updated from Authentik at every login.
- A login that would leave no active global administrator is refused (
last_admin). - Creation, linking, and changes to the global role or groups are recorded in the audit log as
auth.oidc.sync.
Local accounts with the same email
By default (OIDC_AUTO_LINK_VERIFIED_EMAIL=false), an SSO user becomes a separate user even if a local account has the same email. With true, the SSO identity is linked to the local account only when all of the following hold:
email_verifiedis true- Exactly one local account, not yet linked to SSO, has the same email (case-insensitive)
- That local account is neither a global administrator nor an Admin of any Project
Privileged local accounts are never linked automatically, so that an Authentik account cannot take over an administrator. Such logins are refused with privileged_link_required.
Rechecking permissions during a session
This stops people removed from a group in Authentik without waiting for their next login.
- An SSO session checks the current groups with Authentik's UserInfo every
OIDC_RECHECK_SECONDS(default 60 seconds). If the access token has expired, it is refreshed with the refresh token first. - If the user is still in an allowed group, the groups and the global administrator flag are updated and the session continues. Project roles change from the next request.
- If the user has left all allowed groups, all of the user's SSO sessions end and the user's API tokens stop.
- If Authentik refuses the tokens (the user signed out of Authentik, the user was disabled, the refresh token expired), that session ends.
- If Authentik cannot be reached, the API returns 503
oidc_unavailableand keeps the session. Requests are not allowed with unchecked permissions. Once Authentik is back, the same session continues.
Local account sessions and API token requests never call Authentik.
Back-channel logout
If you register the Back-channel logout URI in the Authentik provider, ending a user or session in Authentik also ends the sessions in this application. This is recorded in the audit log as auth.oidc.backchannel_logout.
API tokens of SSO users
A user who only uses API tokens would never notice group changes. So an SSO user's API tokens work only until OIDC_TOKEN_SYNC_MAX_AGE_SECONDS (default 7 days) after the last group sync (a login or a recheck). After that they return 401 identity_sync_required. The tokens are not revoked; signing in once in a browser makes the same tokens work again.
Use Service Account tokens, not personal tokens, for long-running workers, automation, and CI. Service Accounts are exempt from this limit (API tokens and Service Accounts).
Grant Project roles to groups
Instead of granting a role to each person, you can grant a Project role to an Authentik group.
- Create a group per Project in Authentik (for example
mmt-proj-asr-editors). - Add the members to the group and have them sign in with SSO once.
- Open Project settings and click Add group under Authentik group.
- Enter the group name and role, and save.
| Field | Value |
|---|---|
| Group name | The Authentik group name as is. Exact match, including case and spaces. Example: mmt-proj-asr-editors |
| Role | Viewer, Editor, or Admin |
The suggestions list only groups that have been synchronized by someone's login. Type the name directly for a group nobody has signed in with yet.
After saving, the members of the group appear in the Members list with the source "group mmt-proj-asr-editors". The grant is in place.
The group does not need to be in OIDC_ALLOWED_GROUPS. However, its members still need to be in one of the allowed groups to sign in.
Group membership is synchronized at login and at each recheck (every 60 seconds by default). Someone added to the group in Authentik gets the permission within about a minute, even during a session; someone removed loses it within about a minute. A user who only uses API tokens keeps the old groups until the next sync. To stop access immediately, remove the grant in the Project or revoke the tokens.
How the effective role is decided is described in Permissions and roles.