Authentication and access¶
Adriano has no user accounts of its own. People sign in at your OIDC identity provider; Adriano trusts the access token the provider issues and takes the user’s roles from it. CI jobs use separate push tokens that can only submit candidates.
Danger
The development sign-in must be off in production.
ADRIANO_DEV_SHARED_SECRET and
ADRIANO_DEV_AUTH_ENABLED exist for local development.
With the secret set, anyone who knows it can act as any user,
including any reviewer, and approve decisions in their name.
Leave both unset in every shared or production environment, and
verify it after each deployment
(Verifying the development sign-in is off).
How sign-in works¶
sequenceDiagram
actor User
participant UI as Adriano web UI
participant IdP as OIDC provider
participant API as Adriano API
User->>UI: opens Adriano, clicks Sign in
UI->>IdP: redirect to sign-in
User->>IdP: signs in
IdP->>UI: redirect back to /auth/callback
UI->>IdP: exchange code for tokens
IdP-->>UI: access token (audience, roles)
UI->>API: request with access token
API->>IdP: fetch signing keys (first use only)
API->>API: check signature, expiry,<br/>issuer and audience
API->>API: map roles to permissions<br/>(catalog file)
API-->>UI: data, or 401 / 403
The API never takes part in the sign-in itself.
It only checks each request’s token.
It contacts the identity provider the first time it needs the
provider’s signing keys, not at start-up, so an unreachable provider
never stops Adriano.
While the provider is unreachable, requests answer HTTP 503
(auth_unavailable).
Sessions are kept in browser memory only: reloading the page or opening a new tab asks the user to sign in again (usually without a password prompt, while the provider session lasts).
Identity provider contract¶
Register one public client for the web UI (authorization code flow with PKCE, no client secret) and configure:
- Redirect URI
https://<your Adriano address>/auth/callback(orADRIANO_OIDC_REDIRECT_URI).- Post-logout redirect URI
https://<your Adriano address>/(orADRIANO_OIDC_POST_LOGOUT_REDIRECT_URI).- Web origin
Your Adriano address, if the provider restricts browser origins.
- Access token audience
Must contain
ADRIANO_OIDC_AUDIENCE(defaultadr_viewer). Many providers need an explicit audience mapper for this.- Access token roles
A list of role names at the path named by
ADRIANO_OIDC_ROLES_CLAIM(defaultroles;realm_access.rolesfor Keycloak realm roles).- Signing algorithm
RS256. Tokens signed any other way are refused.
- Endpoints
The provider’s token and key endpoints must be on the same origin (scheme, host and port) as
ADRIANO_OIDC_AUTHORITY; the browser blocks requests to any other origin. Adriano’s content security policy allows the web UI to contact that one origin and nothing else besides Adriano itself.
Then set (in .env with Compose, in the ConfigMap on
Kubernetes):
ADRIANO_OIDC_AUTHORITY=https://idp.example.com/realms/adr
ADRIANO_OIDC_CLIENT_ID=adriano-web
ADRIANO_OIDC_AUDIENCE=adr_viewer
ADRIANO_OIDC_ROLES_CLAIM=realm_access.roles
One authority serves both the API (token validation) and the web UI (sign-in); the client ID, scopes and redirect URIs are described in Configuration reference.
Who may do what¶
Three separate grants control access:
readpermissionBrowse and search. Comes from the
rbacsection of the catalog file.operatepermissionStart polls and see source problems in detail. Also from
rbac.- Reviewer
Approve or reject records. Comes from
approval_policy.reviewersin the catalog file, by individual user or by role.
None of them implies another.
A role that rbac does not list grants nothing.
See The catalog file for the syntax.
Tip
To find a reviewer’s issuer|subject, decode one of their
access tokens and read the iss and sub claims.
Push tokens for CI¶
Push tokens are shared secrets, one set per source registration. A push token:
lets a CI job submit candidates for that one registration only;
grants no read access and works on no other request;
is never accepted for sign-in, and sign-in tokens are never accepted for pushes.
See Pushing candidates from CI to create, hand out and rotate them.
What the API answers¶
401withnot_authenticatedThe request carried no token.
401withinvalid_tokenortoken_expiredThe token is wrong for this deployment: bad signature, wrong issuer or audience, or expired.
403withpermission_requiredThe user is signed in, but none of their roles grants the needed permission in
rbac.503withauth_unconfiguredNo sign-in method is configured; nobody can sign in.
503withauth_unavailableThe identity provider (or its signing keys) cannot be reached.
The health endpoint and the API reference page (/api/docs) need
no sign-in; they contain no records and no secrets.
Verifying the development sign-in is off¶
Run these checks after every deployment and after every change to
.env.
The health endpoint reports OIDC only:
curl -fsS https://adriano.example.com/healthz
authmust beoidc.devoroidc+devmeansADRIANO_DEV_SHARED_SECRETis set.The development token endpoint does not exist:
curl -s -o /dev/null -w '%{http_code}\n' \ -X POST https://adriano.example.com/auth/dev/token
The answer must be
404.The start-up log contains neither
DEV AUTH ENABLEDnordev HS256 tokens are accepted:docker compose logs adriano | grep -i 'dev'
The sign-in page offers no “Dev sign-in” button. The production web image never contains it, whatever the settings; if you see one, you are not looking at a production build.
To turn it off, remove both variables from .env (and from the
shell environment and the environment file), then recreate
the container with docker compose up -d adriano (Kubernetes:
kubectl rollout restart deployment/adriano).