Skip to content

OIDC provider

GateKeeper is a full OIDC identity provider. Any application that supports OIDC can delegate authentication to it - Traefik Manager, Grafana, Jellyfin, Portainer, or any custom app.

Instead of each app managing its own login, they redirect users to GateKeeper. GateKeeper handles authentication (password, passkey, TOTP, email OTP) and returns a verified identity token. Apps never see credentials.

PurposeURL
Discoveryhttps://auth.example.com/.well-known/openid-configuration
Authorizationhttps://auth.example.com/authorize
Tokenhttps://auth.example.com/oauth/token
Userinfohttps://auth.example.com/userinfo
JWKS (public keys)https://auth.example.com/keys
Issuerhttps://auth.example.com

Apps that support OIDC discovery only need the discovery URL - everything else auto-configures.

Authorization code + PKCE only. Implicit flow and client credentials are not supported.

ScopeClaims returned
openidsub (user ID)
profilepreferred_username (email)
emailemail, email_verified
offline_accessEnables refresh tokens
  1. Go to /admin/clients and click New client
  2. Enter a display name and optionally an icon URL (fetched and cached server-side at save time)
  3. Choose a client ID - lowercase, digits, dashes. Public and permanent.
  4. Click Generate for the client secret. Copy it - it is not shown again.
  5. Enter redirect URIs one per line. Must match exactly.

See Managing OIDC clients.

Most apps work with just the discovery URL, client ID, and client secret:

Discovery URL: https://auth.example.com/.well-known/openid-configuration
Client ID: your-client-id
Client Secret: your-client-secret
Scopes: openid email profile
from authlib.integrations.flask_client import OAuth
oauth = OAuth(app)
oauth.register(
name='gatekeeper',
server_metadata_url='https://auth.example.com/.well-known/openid-configuration',
client_id='myapp',
client_secret='your-client-secret',
client_kwargs={'scope': 'openid email profile'},
)
provider, _ := oidc.NewProvider(ctx, "https://auth.example.com")
config := oauth2.Config{
ClientID: "myapp",
ClientSecret: "your-client-secret",
Endpoint: provider.Endpoint(),
RedirectURL: "https://myapp.example.com/callback",
Scopes: []string{oidc.ScopeOpenID, "email", "profile"},
}

When a user arrives via /authorize, the login page shows the client’s display name and icon. Direct /login access shows the GateKeeper logo.

TokenLifetime
Access token15 minutes
Refresh token30 days
ID token15 minutes

Tokens are signed with RS256. Keys rotate every 30 days automatically. The previous key stays active so tokens issued just before rotation remain valid.

After a user passes 2FA, a 30-day trusted device cookie skips 2FA on return logins from the same device. Works for both OIDC and ForwardAuth flows.