Skip to main content
This document provides comprehensive information about generic OpenID Connect (OIDC) authentication in Keep. It works with any standards-compliant OIDC provider: Dex, Authentik, Zitadel, Authelia, Kanidm, a plain Keycloak realm, and similar.

Overview

AUTH_TYPE=OIDC enables SSO against any OIDC provider:
  • Authorization code flow with PKCE (performed by keep-ui via NextAuth; the client secret stays on the UI server side only)
  • RS256 bearer token verification in the backend via the provider’s JWKS (discovered from {issuer}/.well-known/openid-configuration)
  • Group-to-role mapping: provider groups are mapped to keep roles (admin / noc / webhook) with comma-separated lists
  • Just-in-time user provisioning: users are created on first sign-in, and their role is refreshed from the token on every API request (a group change on the provider takes effect without re-login)
  • Token refresh (requires the offline_access scope)
This is a single-tenant auth type (tenant keep), like Okta/OneLogin. It does not replace the Keycloak EE integration, which additionally provides custom roles, resource-based permissions, multi-org and in-app user/group management.

How It Works

By default the id_token is validated, because the OIDC spec guarantees aud=client_id for it. Keycloak access tokens default to aud="account", so id_token is the safe default. To validate access tokens instead, set KEEP_OIDC_TOKEN_TYPE=access_token and (if needed) KEEP_OIDC_AUDIENCE. A user whose token carries no group matching any KEEP_OIDC_*_ROLES list gets 403 — there is deliberately no default role.

Environment Variables

Backend (keep-api)

When a group appears in several lists, the priority is admin > noc > webhook.

Frontend (keep-ui)

The provider must allow the redirect URI: https://<your-keep-domain>/api/auth/callback/oidc.

Provider Configuration Examples

Keycloak (any realm, no EE license required)

  1. Create a realm (e.g. keep) or use an existing one. The issuer is https://<keycloak-host>/realms/<realm>.
  2. Create a client:
    • Client type: Confidential
    • Client ID: keep
    • Client authentication: On
    • Standard flow: Enabled, Direct access grants: Disabled
    • Valid redirect URIs: https://<your-keep-domain>/api/auth/callback/oidc
    • Copy the client secret from the Credentials tab.
  3. Add the groups claim (Keycloak does not include groups in tokens by default):
    • Client scopes → select the keep client’s dedicated scope → Add mapper → Group Membership:
      • Token claim name: groups
      • Add to ID token: On (sufficient for the default id_token mode)
      • Full group path: Off (otherwise claims look like /keep-admins — either keep it off, or list full paths in KEEP_OIDC_*_ROLES)
  4. Create groups keep-admins / keep-noc and assign users.
Recommended scopes for Keycloak: openid email profile (see KEEP_OIDC_SCOPES below the examples):
  • the groups scope does not exist in a default realm — the Group Membership mapper adds the groups claim to the token even when the scope is not requested, so simply do not request it;
  • offline_access requires the client to allow offline tokens — a default client returns offline_tokens_not_allowed on the token request. Either omit the scope (refresh tokens keep working for the duration of the SSO session) or enable offline access for the client.

Dex

Dex is useful on its own and as an LDAP/AD federation front (its ldap connector brings directory groups into the groups claim).
Notes:
  • To skip the consent screen set oauth2.skipApprovalScreen: true (not skipApproval).
  • Static (staticPasswords) users do not carry a groups claim — they cannot get a role in keep by design. Use them as break-glass IdP accounts, or put directory users in the mapped groups.
  • With the ldap connector, request the groups scope — Dex adds the groups claim only when that scope is granted.

Authentik

  1. Create an OAuth2/OpenID provider:
    • Client type: Confidential
    • Redirect URIs: https://<your-keep-domain>/api/auth/callback/oidc
    • Scopes: add email, profile, offline_access and a group-membership scope mapping (Authentik’s default “groups” property mapping emits the groups claim).
  2. The issuer is shown on the provider page: https://authentik.example.com/application/o/<slug>/.
  3. Assign users to keep groups (keep-admins/keep-noc) and use the same env variables as in the examples above.

Security Notes

  • Tokens are verified on every API request: RS256 signature via JWKS, iss = KEEP_OIDC_ISSUER, aud = client id (or override), exp with a 60s leeway. Key rotation on the provider is handled automatically (JWKS is re-fetched for unknown key ids).
  • The discovery document is fetched once per issuer and cached; it is not requested per API call.
  • No mapped group → 403 (there is no fallback role).
  • API keys are unaffected by provider availability (they use a separate code path). If the provider is down, previously issued tokens stay valid until they expire, but no new ones can be obtained.
  • Sign out clears the keep session; the SSO session at the provider stays alive (same behavior as the Okta/OneLogin integrations).

Troubleshooting