Skip to main content

SSO pages

Every UI surface involved in the SSO flow. For the mental model see Identity and SSO; for setup see Admin → Configure global SSO or Admin → Configure per-org SSO.

/login — the picker​

Anonymous users land here. The page asks how to sign in.

ElementBehaviour
Email + password formLocal-password path. Available unless require_sso=true blocks it.
Sign in with SSO buttonOpens the realm picker (below)
Register linkVisible only when public registration is enabled and the license allows new users

The page does NOT show org-specific SSO buttons up front — those require a realm slug, which the next step asks for.

/login realm picker (modal)​

Click Sign in with SSO → small dialog:

FieldNotes
Organization realmType your org slug (e.g. acme). Leave blank to use global SSO.
Continue buttonPOSTs to /api/auth/discovery with the slug

Discovery response shapes the next step:

  • oidc button → org's IdP found, click to start redirect
  • oidc (global) → no per-org IdP, falling back to global
  • local button → no SSO at all, you're back at password
  • No button at all → "No SSO provider for that realm" error (slug doesn't exist OR exists but has no SSO and no global is configured)

/sso — start​

URL: /sso?slug=<org-slug>&redirect=<post-login-path>

This route is short-lived. The browser hits it, the backend builds an encrypted state token, redirects you to the IdP's authorization URL. You shouldn't see this page in normal flow — it's a server-side bounce.

If you DO see it (white screen, no redirect): the SSO config has a malformed issuer URL or the discovery call failed. Check the backend logs.

IdP redirect​

Your browser is now at the IdP (Auth0, Keycloak, Okta, Azure AD, …). The dtedge UI has no visibility here. You authenticate however the IdP requires — password, MFA, hardware token, whatever.

On success the IdP redirects back to /sso/callback?code=...&state=....

/sso/callback — server-side​

Like /sso, this is short-lived. The backend:

  1. Decrypts state, verifies freshness (10 min window)
  2. Exchanges the code for ID + access tokens
  3. Verifies the ID token signature against the IdP's JWKS
  4. Verifies the nonce matches what we put in state
  5. Extracts claims (email, name, sub, groups)
  6. Links / provisions the user
  7. Reconciles roles from group mapping (if configured)
  8. Issues a dtedge JWT
  9. Redirects to /sso/finish?token=<jwt>

/sso/finish — token landing​

The page that receives the freshly minted dtedge JWT. It stores the token in localStorage and redirects to the original destination (or / by default).

In a normal flow you see this page for a fraction of a second. If you see it stuck, JavaScript or storage may be disabled.

/sso/error — failure landing​

Where SSO failures end up. The URL carries an error code as a query param:

CodeMeaning
INVALID_STATEThe state token was missing, expired, or tampered with. Try logging in again.
STATE_EXPIREDThe state token was older than 10 minutes (you sat on the IdP login page too long). Try again.
NONCE_MISMATCHThe ID token's nonce doesn't match what we sent. Tampering or stale browser tab.
ID_TOKEN_INVALIDThe IdP returned a malformed token. Check the IdP side.
PROVIDER_GONEThe SSO config was deleted between when you started login and when you came back. Admin issue.
EMAIL_CLAIM_MISSINGThe IdP didn't include an email claim. Fix the IdP scope.
NOT_PROVISIONEDAuto-provision is off and you're not in dtedge yet. Admin needs to invite you.
LINK_FAILEDInternal failure during identity link. Backend log has details.

Organizations → <org> → SSO tab​

Org admin's per-org SSO config page. The form has:

SectionFields
ProviderIssuer URL, Client ID, Client secret
Scopes + claimsScopes (space-separated), Claim mappings (email/name/groups)
ProvisioningAuto-provision toggle, Default role dropdown
Group → role mappingAdd row (IdP group name → org role dropdown)
PolicyRequire SSO toggle
URIsRedirect URI, Back-Channel Logout URI, Post-Logout Redirect URI (read-only; for pasting into the IdP app config)
ActionsSave / Remove

Each save runs PingIssuer (discovery URL must respond) and validates each mapping row's role exists.

Admin → Settings → Global SSO​

Super-admin's install-wide SSO. Same shape as per-org, plus:

SectionFields
Org-role assignmentsGrid of (IdP group, org, role) rows; the role dropdown is filtered to the picked org's roles

The Default role field is hidden on this surface (less meaningful for global SSO — the org-role assignment grid usually handles role placement).

See also​