OIDC-federated user login
At a glance. Stack this on top of any other topology to change how users authenticate. Users click “Sign in with
<provider>”, authenticate at your upstream IdP (Google Workspace / Okta / Entra / Auth0), and AuthPlane auto-provisions or links a local account. Token issuance still happens in AuthPlane — federation only changes login. One upstream IdP at a time; use Dex as a broker for multi-provider setups.
Topology
flowchart LR
User["User<br/>browser"]
IdP["Upstream IdP<br/>(Okta, Google, Entra)"]
AS["AuthPlane"]
Topo["Agent, MCP,<br/>Broker, ...<br/>(any topo.)"]
User -->|login| IdP
IdP -->|ID token| User
AS -->|OAuth code exchange| IdP
AS -->|"consent + token flow<br/>proceeds as normal"| Topo
Only login changes. Consent, token issuance, resource binding, scope enforcement — all identical to the non-federated version of your topology.
Flow
sequenceDiagram
participant Agent
participant AS as AuthPlane
participant User
participant Google
Agent->>AS: /oauth/authorize?resource=…&scope=…
AS->>User: Login page — clicks "Sign in with Google"
User->>AS: GET /oidc/start?redirect=…
AS->>Google: 302 to https://accounts.google.com/o/oauth2/v2/auth?…
User->>Google: authenticates (MFA, SSO, whatever)
Google->>AS: 302 to /oidc/callback?code=…
AS->>Google: POST /token (exchange code for ID token)
Google->>AS: ID token with email, name, sub, exp, ...
AS->>AS: validates ID token (JWKS from Google's discovery)
AS->>AS: looks up local user by (provider, provider_sub) — creates one<br/>on first sight using email + name from the ID token
AS->>User: 302 to /consent (or /authorize continuation)
AS->>AS: (rest of OAuth flow is standard)
Then: consent → auth code → /oauth/token → tokens. Every step from /oauth/authorize onward is identical to any other topology on this section.
When to use
- Your org already uses Google Workspace / Okta / Entra ID / Auth0 / any OIDC provider.
- You don’t want to manage passwords in AuthPlane.
- You need your IdP’s MFA, conditional access, session policies, group memberships.
- AuthPlane is being deployed for a team with existing corporate accounts.
Don’t use when:
- Your users are external — federation to a corporate IdP won’t make sense.
- You need multiple upstream IdPs simultaneously (Google + Okta at the same time) → use Dex as a broker in front of AuthPlane.
- Users don’t have a browser (headless services) → XAA with
jwt-bearergrant is the right move.
How to configure
Full walkthrough per provider in Guides: Federate to your IdP. Summary:
Register at your IdP:
- App type: web application (OIDC).
- Redirect URI:
https://<your-authserver>/oidc/callback. - Note the client_id + client_secret + issuer URL.
AuthPlane config:
oidc:
enabled: true
issuer: https://accounts.google.com # or your Okta / Entra / Auth0 issuer
client_id: "your-client-id"
client_secret: "your-client-secret" # or use client_secret_ref (env-var name)
display_name: Google # login button text
redirect_uri: https://auth.example.com/oidc/callback
scopes: [openid, email, profile]
Env-var equivalents: AUTHPLANE_OIDC_ENABLED, AUTHPLANE_OIDC_ISSUER, AUTHPLANE_OIDC_CLIENT_ID, AUTHPLANE_OIDC_CLIENT_SECRET, etc.
How AuthPlane handles it
/oidc/start— generates state + PKCE, sets HTTP-only session cookie, 302s to upstream/authorize./oidc/callback— validates state (HMAC-signed), exchanges code, validates the ID token against upstream JWKS (cached viaxaa.jwks_cache_ttl).UserAuthService— looks up the local user by the stable(provider, provider_sub)pair from the ID token. If present, that’s the account. If absent, auto-provisions a local user, using the ID token’semailandnameclaims to populate the new row (email is not the match key — a user can rename their email at Google and the same account will still resolve).- Session cookie is stamped; user is redirected back to
/oauth/authorize— the OAuth flow that triggered login continues from where it left off.
oidc.show_local_login: false hides the password form entirely — everyone must authenticate through the IdP.
Verify
# Metadata check — /.well-known/openid-configuration doesn't announce OIDC (that's the IdP)
# but the login page shows the button
curl -s http://localhost:9000/login | grep -i "sign in with google"
# After login, user appears in the admin table
authserver admin user list
# → email=alice@example.com, provider="google", provider_sub="1234567890"
See also
- Guides: Federate to your IdP — full per-provider setup
- Reference: Configuration → OIDC — every knob
- Concepts: Cross-App Access (XAA) — the other enterprise-IdP integration (agent identity assertion, not user login)