Skip to main content

Identity providers

Planeon authenticates everyone — administrators and end users alike — with standard OpenID Connect. There's no bundled identity provider and no local password store: you point Planeon at your own OIDC-compliant provider, and any provider that exposes an OpenID discovery document and can emit a groups claim works — Keycloak, Microsoft Entra ID, Okta, Authentik, and others.

How sign-in works

The identity provider answers "who is this user?"; Planeon's own access management answers "what can they do here?". At sign-in:

  1. Your identity provider issues an OIDC token to the user's browser.
  2. Planeon validates the token's issuer, audience, signature, and expiry.
  3. Planeon reads the user's identity (subject, email, name, username) and two configurable claims — a groups claim and a roles claim.
  4. Those claims are kept as external facts on the user; they only become local access once mapped through an OIDC group binding.

Generic OIDC setup

Every provider is configured with the same handful of values:

  • Redirect URIs — register three URIs on the application in your identity provider, all on your Planeon origin (shown here as https://<your-planeon-host>; for a local install, use http://localhost:3000):

    • https://<your-planeon-host>/auth/callback — where the provider sends the user back after they sign in.
    • https://<your-planeon-host>/auth/signed-out — the visible landing page after sign-out; providers validate the post-logout redirect against this registered list.
    • https://<your-planeon-host>/auth/frontchannel-logout — the front-channel logout notification URL the provider loads (invisibly) to clear Planeon's local sign-in state when the session is ended on the provider's side.

    With only /auth/callback registered, login works but sign-out breaks — typically with a provider error such as "Bad Request: The request is otherwise malformed" when the post-logout redirect isn't in the allowed list.

  • Client ID / secret — Planeon's frontend is a browser-only single-page app, so it authenticates as a public OIDC client (PKCE, no client secret) rather than a confidential one. Register a public client and use the same client ID on both the frontend and backend configuration.

  • Issuer URL — the exact URL your provider puts in a token's iss claim. The browser must be able to reach <issuer>/.well-known/openid-configuration directly, so avoid internal or container-only hostnames here.

  • Scopesopenid profile email groups offline_access. The offline_access scope is what lets your provider issue a refresh token, so a long-open browser tab can renew its session silently instead of failing when the access token expires.

  • Group claim — the claim Planeon reads to determine group membership, groups by default. Providers that nest claims (for example, Keycloak's realm roles) can be read with a dot-path like realm_access.roles instead of a plain top-level key. Whichever claim you configure, remember that the claim by itself grants nothing until you map its values to local groups with an OIDC group binding.

Tested providers

Keycloak. Keycloak emits realm roles nested at realm_access.roles and client roles at resource_access.<client-id>.roles; groups need an explicit "Group Membership" mapper added to the client (or a shared client scope) to appear in the token, typically as a top-level groups claim. The issuer is https://<keycloak-host>/realms/<realm>. With the mapper's "Full group path" option left off, a user in group /VDI-Admins emits the plain value VDI-Admins rather than a path with a leading slash.

Microsoft Entra ID. Use the v2.0 endpoint: https://login.microsoftonline.com/<tenant-id>/v2.0. Entra's groups claim contains group object GUIDs by default unless you configure it to emit display names instead; the more robust option is binding on app roles (the roles claim) instead of raw groups. Watch for the group overage limit — a user in roughly 200+ groups gets no groups array in the token at all, only a pointer to the Microsoft Graph API, which Planeon does not follow — binding on app roles avoids this entirely.

Okta. Okta's default "org" authorization server doesn't emit a usable groups claim, so use a custom Authorization Server (the built-in default one works) and add a groups claim to it explicitly. The issuer is https://<your-org>.okta.com/oauth2/<authorization-server-id>, and Okta emits groups as a plain JSON string array with no special handling needed on Planeon's side.

Authentik. Authentik is the identity provider Planeon's own local development stack ships behind an optional profile — a convenient default, not a requirement. It needs nothing provider-specific beyond the generic OIDC recipe above: create an OAuth2/OpenID provider and application, set the client type to public, enable the Authorization Code grant with PKCE, and add a groups scope mapping so group membership reaches the token.

What's next

Detailed, click-through setup guides for each of these providers are planned as follow-up additions to this page.