Authentication (OIDC)
Last updated: October 26, 2026
Since version 4.4.0, users sign in to xltrail through your own OpenID Connect (OIDC) identity provider (IdP), such as Microsoft Entra ID, Okta, Keycloak or AD FS. xltrail has no password, LDAP / Active Directory or one-time-code login, and there is no built-in admin account: user accounts and administrator rights come from the IdP.
Upgrading from 4.3.x or earlier? Read the upgrade notes for Compose, Helm or OpenShift first: the migration is irreversible.
xltrail does not bundle an identity provider. Register xltrail as a client at the IdP your organization already uses.
1. Register a client at your IdP
Register a confidential (web) client that uses the authorization code flow:
| Value | |
|---|---|
| Redirect URI | https://<HOSTNAME><BASE_URL>/login/oidc/callback |
| Post-logout redirect URI | https://<HOSTNAME><BASE_URL>/logout/done |
| Scopes | openid profile email |
Use http:// if HTTPS_ENABLED is off. xltrail builds both URIs from HOSTNAME and BASE_URL; there is no setting for them.
2. Administrators
A user is an administrator if the claim OIDC_ADMIN_CLAIM equals OIDC_ADMIN_VALUE or, for list claims, contains it. The IdP is the only source of administrator rights; they are re-evaluated at every sign-in, so to grant or revoke them, change the user’s assignment at the IdP and have the user sign in again. The Users page in xltrail shows the role but cannot change it.
- Microsoft Entra ID: app role
xltrail-admin,OIDC_ADMIN_CLAIM=roles,OIDC_ADMIN_VALUE=xltrail-admin, see Microsoft Entra ID. - Okta, AD FS: map a group or role to a claim in the ID token.
- Keycloak: group-membership or role mapper, e.g. claim
groups, valuexltrail-admins.
Some IdPs only include the claim when an extra scope is requested; add it to OIDC_SCOPES, for example openid profile email groups.
To check who is an administrator, run the server command python manage.py users list --admins (without --admins it lists all users with id, email, name, role and whether they are linked to the IdP):
# Compose
docker exec xltrail-server-1 python manage.py users list --admins
# Helm (Kubernetes / OpenShift)
kubectl exec xt-app-0 -c server -- python manage.py users list --admins3. Settings
With Compose, set the settings under their own names in /etc/xltrail/xltrail.conf (see Compose configuration). With Helm (Kubernetes / OpenShift), set the chart value in the “Helm value” column under xltrail in your values.yaml instead (see Kubernetes: OIDC settings).
| Setting | Helm value | Required | Default | Description |
|---|---|---|---|---|
OIDC_ISSUER_URL | oidcIssuerUrl | yes | Issuer URL, exactly as the issuer in the IdP’s discovery document (a trailing slash is tolerated); discovery is read from <issuer>/.well-known/openid-configuration | |
OIDC_CLIENT_ID | oidcClientId | yes | Client ID | |
OIDC_CLIENT_SECRET (or SECURE_OIDC_CLIENT_SECRET) | oidcClientSecretSecretName (name of a Secret with key OIDC_CLIENT_SECRET) | yes | Client secret | |
OIDC_ADMIN_CLAIM | oidcAdminClaim | yes | Claim that grants administrator rights | |
OIDC_ADMIN_VALUE | oidcAdminValue | yes | Value of OIDC_ADMIN_CLAIM (or element of a list claim) that grants administrator rights | |
OIDC_SCOPES | oidcScopes | no | openid profile email | Space-separated scopes requested at sign-in |
OIDC_TRUST_EMAIL | oidcTrustEmail | no | false | Link existing users by email even when the IdP does not mark it verified |
OIDC_STATE_TTL | oidcStateTtl | no | 600 | Seconds a sign-in may take before it has to be restarted (Helm only: the Compose 4.4.0 release does not pass it to the app) |
LOGOUT_REDIRECT_URL | logoutRedirectUrl | no | unset | Where /logout/done redirects (a path is relative to BASE_URL); unset shows a signed-out page |
AUTH_TOKEN_EXPIRY | authTokenExpiry | no | 30d | Lifetime of the xltrail session cookie, format <d>d<h>h<m>m<s>s |
HTTP_REQUEST_TIMEOUT | httpRequestTimeout | no | 10 | Timeout in seconds for outgoing HTTP requests, including those to the IdP (Helm only: the Compose 4.4.0 release does not pass it to the app) |
Example for Microsoft Entra ID in xltrail.conf (for the values.yaml equivalent, see Kubernetes: OIDC settings):
OIDC_ISSUER_URL=https://login.microsoftonline.com/<tenant-id>/v2.0
OIDC_CLIENT_ID=<application-client-id>
OIDC_CLIENT_SECRET=<client-secret>
OIDC_SCOPES="openid profile email"
OIDC_ADMIN_CLAIM=roles
OIDC_ADMIN_VALUE=xltrail-adminStartup and IdP availability
xltrail starts even if the OIDC settings are missing or the IdP cannot be reached; OIDC discovery is lazy, i.e. the discovery document is only fetched when it is first needed, not at startup.
- While a required setting is missing, nobody can sign in: the sign-in page shows “Single sign-on is not configured” with the names of the missing settings, and the server log lists them.
- While the IdP cannot be reached, the sign-in page shows “The identity provider is currently unreachable”. xltrail retries at most every 30 seconds when the sign-in page or the health endpoint is requested, so no restart is needed once the IdP is back.
- The health endpoint
/api/healthreports"oidc": "unconfigured","unreachable"or"ok".
Internal or self-signed IdP certificates
Connections to the IdP use the server’s system CA trust store. If your IdP’s certificate is issued by an internal CA (or is self-signed), add that CA to the system trust store, which needs no further setting: with Compose via CA_CERTIFICATES, with Helm via xltrail.caCertificatesSecretName in your values.yaml.
The server enforces strict X.509 checks: a CA certificate must have basicConstraints CA:TRUE and a keyUsage extension that includes keyCertSign, otherwise verification fails with “CA cert does not include key usage extension” even though the CA is trusted.
4. First sign-in and existing users
- A user signing in for the first time gets an account if a seat is free; otherwise the sign-in fails with “All licensed user seats are taken”. There is no invitation step: assign the user to the xltrail application at your IdP.
- If an account without IdP link and with the same verified email (not case sensitive) exists, for example a user from before 4.4.0, it is linked instead, keeping history and permissions. If no existing account, or more than one, has that email, a new account is created, which takes a seat.
- Some IdPs never mark emails verified (Keycloak with LDAP federation, AD FS, Microsoft Entra ID without
xms_edov). SetOIDC_TRUST_EMAIL=trueonly if users cannot change their own email at the IdP. - At each sign-in, a user’s name and verified email are updated from the IdP.
- Removing a user at the IdP stops them from signing in but does not free their seat; remove the user under Settings > Users in xltrail as well.
Microsoft Entra ID
Register xltrail as a single-tenant app in your Entra tenant.
App registration
- Add a Web platform with two redirect URIs:
https://<HOSTNAME><BASE_URL>/login/oidc/callbackandhttps://<HOSTNAME><BASE_URL>/logout/done. Entra accepts a post-logout redirect only if it is registered as a redirect URI. - Leave the front-channel logout URL empty; xltrail does not support IdP-initiated logout.
- Set
OIDC_CLIENT_IDto the application (client) ID andOIDC_CLIENT_SECRETto a client secret of the registration. - Set
OIDC_ISSUER_URLtohttps://login.microsoftonline.com/<tenant-id>/v2.0, verbatim. It must match theissuerin the discovery document, so do not usecommon,organizationsor the tenant’s domain name. - Keep
OIDC_SCOPESatopenid profile email. Do not request scopes for other APIs: xltrail reads the ID token and, for missing claims, the userinfo endpoint, which needs a Microsoft Graph token.
Administrators
- Define an app role, e.g.
xltrail-admin, on the app registration and assign it to the admin users (or a group of them). - Set
OIDC_ADMIN_CLAIM=rolesandOIDC_ADMIN_VALUE=xltrail-admin. - Prefer app roles over group claims: Entra omits the
groupsclaim when a user is in too many groups (overage), and the user then loses admin rights.
Linking existing users
Entra never emits email_verified, so existing xltrail users are not linked by email out of the box. Either:
- add the optional claim
xms_edov(email domain owner verified) to the ID token of the app registration, or - set
OIDC_TRUST_EMAIL=true, but only if users cannot change their own email in Entra.
Troubleshooting
- Redirect URI mismatch: the registered URI must match
HOSTNAME,BASE_URLand the scheme exactly. - “Single sign-on is not configured”: set the settings listed on the page and restart xltrail.
- “The identity provider is currently unreachable”: the server log says why discovery failed, for example
OIDC_ISSUER_URLnot matching theissuerin the discovery document, a network/proxy problem, or a certificate from a CA that is not in the system trust store. /login?error=token_invalid: usually a wrongOIDC_CLIENT_SECRET; the server log showscode exchange failed: invalid_client.- Signed in but not an administrator: check the token claims at the IdP; the value must match
OIDC_ADMIN_VALUEexactly. - Entra ID: do not request scopes for other APIs; xltrail reads the userinfo endpoint, which needs a Microsoft Graph token. Keep
OIDC_SCOPESatopenid profile email.