OIDC authentication¶
Operator login is OIDC-only. The configured Authority is the URL of any provider that supports the Authorization Code flow with PKCE and OIDC discovery — Keycloak, Okta, Auth0, Azure Entra ID, Google Workspace, AWS Cognito, ADFS, GitLab, GitHub Enterprise.
Settings¶
| Key | Required | Notes |
|---|---|---|
Authentication:Oidc:Authority | yes | Issuer URL (must equal the iss claim in returned tokens) |
Authentication:Oidc:ClientId | yes | Application ID |
Authentication:Oidc:ClientSecret | yes (confidential client) | Secret value; treat as a password |
Authentication:Oidc:RoleClaim | no | Default ampora:role. Where Ampora reads the role from |
Authentication:Oidc:TenantClaim | no | Default tenant. Where Ampora reads the tenant discriminator from |
Authentication:Oidc:CallbackPath | no | Default /signin-oidc. Override if you mount Ampora under a path |
Provider checklist¶
Any compliant provider needs to do four things:
- Issue ID tokens signed with RS256 (or another JWS alg supported by the .NET OIDC handler).
- Honour the
openid profile emailscopes. - Carry an Ampora role claim — see below for the mapping.
- Carry a tenant discriminator claim if you run multi-tenant.
Role mapping¶
Ampora has three roles:
Admin— full read/writeOperator— rollouts, no settings/governanceViewer— read-only
The role is read from a single string-or-array claim. Default claim name is ampora:role. Configure your provider to emit one of:
- a single string value:
"Admin" - a list:
["Operator", "Viewer"](highest wins)
The first user to log in is bootstrapped as Admin if no users exist yet. After that, role assignment follows the claim.
Keycloak¶
Use the local development stack as a working blueprint — deploy/dev/keycloak/realm-ampora.json ships:
- a confidential client
ampora-web, - a protocol mapper that emits
ampora:rolefrom a user attribute, - three users (
alice/Admin,bob/Operator,carol/Viewer).
For production-grade Keycloak:
- Create a confidential client
ampora-web. Set: - Valid Redirect URIs to
https://AMPORA_HOST/signin-oidc. - Valid Post Logout Redirect URIs to
https://AMPORA_HOST/signout-callback-oidc. - Web Origins to
https://AMPORA_HOST. - Add a User Attribute mapper:
- User Attribute:
ampora_role - Token Claim Name:
ampora:role - Claim JSON Type:
String - Add to ID token, access token, userinfo: yes.
- Or, alternatively, a Group Membership mapper that emits group membership as
ampora:role. Combined with three groups (ampora-admin,ampora-operator,ampora-viewer) this gives group-based role assignment without per-user attributes.
Azure Entra ID (Azure AD)¶
- Register an application:
- Redirect URI:
https://AMPORA_HOST/signin-oidc - Front-channel logout URL:
https://AMPORA_HOST/signout-callback-oidc - Add a client secret. Copy it into
Authentication__Oidc__ClientSecret. - Token configuration → Add optional claim →
groups. Use a transitive groups assignment if your AAD is large. - Add an App role for each Ampora role (Admin, Operator, Viewer). Assign users / groups to roles.
- Set
Authentication__Oidc__RoleClaimtoroles(the standard claim name AAD uses for app roles).
Authority: https://login.microsoftonline.com/{tenant}/v2.0 (the /v2.0 suffix is mandatory).
Okta / Auth0¶
- Create an OIDC application of type "Web".
- Redirect URI:
https://AMPORA_HOST/signin-oidc. - Map a user property to the
ampora:roleclaim via the Authorization Servers → Claims UI. Use a Groups claim if you prefer group-based assignment. Authority:https://{tenant}.okta.com/oauth2/default(Okta) orhttps://{tenant}.auth0.com(Auth0).
Common pitfalls¶
- Issuer mismatch: the URL in
Authoritymust equal theissclaim exactly, including trailing slash and protocol. The dev stack works around this withhost.docker.internalso the browser and the Ampora container resolve the IdP through the same hostname. - Confidential client with
client_secret_post: some providers default toclient_secret_basic, others toclient_secret_post. .NET's OIDC handler defaults toclient_secret_post. If your IdP rejects, switch the client to "post" auth or setAuthentication__Oidc__ClientAuthentication=ClientSecretBasic. - Path-based mount: if you serve Ampora under
https://AMPORA_HOST/ampora, overrideCallbackPathto/ampora/signin-oidcand update redirect URIs accordingly.
Verifying the login flow¶
Once configured, hitting https://AMPORA_HOST should:
- Redirect to your IdP's login page.
- After login, redirect back to
/signin-oidc. - Show the Ampora dashboard with the user's name in the top-right.
- The user menu shows the active Tenant and Role.
If any step fails, see Troubleshooting → OIDC for the diagnostic walkthrough.