docs

Authentication — Keycloak

In Keycloak mode users sign in with a branded password form against your own Keycloak realm. The API validates the realm's tokens. Use this when you self-host identity rather than federating to Entra.

Import the realm

edgentia ships a realm export (deploy/keycloak/real/edgentia-realm.json in the edgentia-core repo). Import it into your Keycloak (mount it at /opt/keycloak/data/import with --import-realm, or import via the admin console). It defines:

  • Realm edgentia, self-registration off.
  • Clients:
    • edgentia-frontend — public SPA client (PKCE), no secret. Add your public URL to its redirect URIs (https://edgentia.acme.com/*).
    • edgentia-api — confidential client with a service account holding the realm-management roles view-realm, view-users, query-users, manage-users (so the directory picker / invites work). Its secret is what you pass as the admin client secret below.
  • Realm roles: platform-admin, workspace-admin, analyst, operator, viewer.
  • Token mapper job_title — surfaces the user's job title on /v1/me.

The export seeds one bootstrap platform-admin owner from the BOOTSTRAP_OWNER_* values — set these for your install (username, email, name, password). Sign in as that owner first, then create workspaces and members.

Configuration

VariableRequiredNotes
Auth__AuthorityIssuer URL the API uses to fetch metadata + signing keys, e.g. https://kc.acme.com/realms/edgentia. App won't start without it.
Auth__AdminClientIdedgentia-api.
Auth__AdminClientSecretThe edgentia-api client secret — must match the realm.
Auth__ValidIssueroptionalSet when the browser-facing issuer differs from Auth__Authority (see below).
Auth__AudienceoptionalLeave empty to validate by issuer only.
Auth__RequireHttpsMetadataoptional (true)false only if the metadata endpoint is plain HTTP.

Helm: auth.mode=keycloak, auth.keycloak.authority, auth.keycloak.adminClientSecret, auth.keycloak.validIssuer. Compose: KEYCLOAK_AUTHORITY, KEYCLOAK_ADMIN_CLIENT_SECRET.

The browser-vs-internal issuer split

Keycloak is often reachable at one hostname from the API (an in-cluster service, used for metadata + signing keys) and another from the browser (the public URL, which the token's iss reflects). When they differ:

  • Auth__Authority → the internal URL (keys/metadata), e.g. http://keycloak:8080/realms/edgentia.
  • Auth__ValidIssuer → the browser-facing URL (the iss to validate), e.g. https://edgentia.acme.com/auth/realms/edgentia.

The API fetches keys from Authority but validates the issuer against ValidIssuer. The SPA derives its Keycloak URL from ValidIssuer. Keycloak should trust your proxy's X-Forwarded-* headers (KC_PROXY_HEADERS=xforwarded) so it emits the correct public issuer.

User management

Keycloak supports up to management level 2 (in-app invites + directory). The edgentia-api service account reads the realm directory; without its client secret the "add member" picker degrades to adding members by id.