Identity provider OIDC#
Le persone accedono a manent tramite il tuo identity provider. L'API verifica i token di accesso JWT che emette (firma, issuer, audience, scadenza), prende nome utente e gruppi dai loro claim, e i binding dell'RBAC trasformano i gruppi in ruoli. L'interfaccia web fa accedere gli utenti con Authorization Code e PKCE; la CLI invia un token ottenuto dal provider.
Cosa serve
Un provider OIDC (Keycloak, Microsoft Entra ID, Okta, Google, Auth0, Dex…) · i permessi per registrare applicazioni · manent servito in HTTPS (l'accesso dal browser lo richiede)
sequenceDiagram
participant B as Browser (interfaccia manent)
participant I as Identity provider
participant A as API di manent
B->>I: Authorization Code + PKCE (client manent-ui)
I-->>B: token di accesso (aud = manent, groups = [...])
B->>A: Authorization: Bearer <token>
A->>I: discovery + JWKS (all'avvio, poi alla rotazione delle chiavi)
A-->>B: risposta, secondo i ruoli dei gruppi
Cosa si aspetta manent nel token#
| Claim | Impostazione | Default |
|---|---|---|
iss |
auth.oidc.issuer |
|
aud |
auth.oidc.audience |
|
| nome utente | auth.oidc.username_claim |
obbligatorio: vedi sotto |
| gruppi | auth.oidc.groups_claim |
groups |
L'identità diventa oidc:<nome utente>, come mostra manent whoami e come viene registrata nell'audit.
Scegliere il claim del nome utente#
username_claim è obbligatorio: sul nome utente si basano i binding per soggetto, la regola dei quattro occhi nelle approvazioni e l'audit. Scegli un claim unico per ogni utente e che gli utenti non possano cambiare da soli. Un token senza quel claim viene rifiutato: manent non ripiega mai su un altro claim.
| Provider | Claim | Note |
|---|---|---|
| Keycloak | preferred_username |
Leggibile. Lascia disattivato Realm settings → Edit username, come da default, così gli utenti non possono rinominarsi. |
| Microsoft Entra ID | oid |
L'object ID, immutabile. Microsoft sconsiglia preferred_username per le autorizzazioni: gli amministratori possono cambiarlo e assegnarlo di nuovo a un altro utente. |
| Okta | sub |
Nei token di accesso di un authorization server personalizzato, sub è il login dell'utente. |
| Qualsiasi | sub |
Unico e stabile per la specifica OIDC, ma spesso un ID opaco. |
Cambiare username_claim su un'installazione esistente cambia tutte le identità: le approvazioni in attesa confrontano il vecchio nome del richiedente con il nuovo nome di chi approva, quindi esauriscile prima e aggiorna binding e identità di Slack.
Configura il provider#
- Nel realm (per esempio
corp, issuerhttps://sso.example.com/realms/corp) crea un clientmanentche rappresenta solo l'API: Client authentication disattivata, nessun flusso attivo. Il suo ID è l'audience. - Crea un client
manent-uiper l'interfaccia web:- Client authentication disattivata (client pubblico), Standard flow attivo, Direct access grants disattivato;
- Valid redirect URIs
https://manent.example.com/auth/callback, Valid post logout redirect URIshttps://manent.example.com/, Web originshttps://manent.example.com; - Advanced → Proof Key for Code Exchange Code Challenge Method:
S256.
- In Client scopes → manent-ui-dedicated aggiungi due mapper:
- Audience: Included Client Audience
manent, Add to access token attivo; - Group Membership: Token Claim Name
groups, Full group path disattivato, Add to access token attivo.
- Audience: Included Client Audience
- App registration
manent-api(l'API):- Expose an API: Application ID URI
api://manent, aggiungi uno scopeaccess; - nel Manifest imposta
requestedAccessTokenVersion(oaccessTokenAcceptedVersionnel manifest precedente) a2: i token v2 hanno comeaudil client ID dell'applicazione; - App roles: crea ruoli come
manent.deployeremanent.approvere assegnali ai gruppi in Enterprise applications → manent-api → Users and groups. I ruoli arrivano nel claimrolescon nomi leggibili, mentre il claimgroupsconterrebbe gli object ID.
- Expose an API: Application ID URI
- App registration
manent-ui(l'interfaccia web):- Authentication: piattaforma Single-page application, redirect URI
https://manent.example.com/auth/callback, front-channel logouthttps://manent.example.com/; - API permissions: My APIs → manent-api → access, poi concedi il consenso amministrativo.
- Authentication: piattaforma Single-page application, redirect URI
auth:
mode: enabled
oidc:
issuer: https://login.microsoftonline.com/<tenant-id>/v2.0
audience: <client ID di manent-api>
username_claim: oid # immutabile: i soggetti diventano object ID
groups_claim: roles
ui:
client_id: <client ID di manent-ui>
scopes: [openid, profile, "api://manent/access"]
rbac:
bindings:
- {groups: [manent.deployer], role: deployer, applications: ["*"], environments: [dev, test]}
- {groups: [manent.approver], role: approver, applications: ["*"], environments: [prod]}
Lo scope api://manent/access fa emettere a Entra il token di accesso per l'API, con l'audience giusta.
- Security → API → Authorization Servers: usa un authorization server personalizzato (o creane uno chiamato
manent) con audienceapi://manent. Il suo issuer èhttps://<org>.okta.com/oauth2/<id del server>. - In quel server, Claims → Add Claim: nome
groups, incluso nell'Access Token, tipo di valore Groups, filtro per esempio Starts withmanent-. - Applications → Create App Integration → OIDC → Single-Page Application: grant type Authorization Code, sign-in redirect URI
https://manent.example.com/auth/callback, sign-out redirect URIhttps://manent.example.com/; assegna i gruppi che possono usare manent. - Security → API → Trusted Origins: aggiungi
https://manent.example.comper il CORS.
Per un provider con una CA privata aggiungi auth.oidc.ca_file. manent legge il documento di discovery e le chiavi del provider all'avvio di serve (o api), e ricarica le chiavi quando ruotano.
Associa i gruppi ai ruoli#
rbac:
bindings:
- {groups: [team-shop], role: deployer, applications: ["shop*"], environments: [dev, test, staging]}
- {groups: [team-shop], role: tester, applications: ["shop*"], environments: [prod]}
- {groups: [release-managers], role: operator, applications: ["*"], environments: ["*"]}
- {groups: [cab], role: approver, applications: ["*"], environments: [prod]}
- {groups: [platform], role: admin, applications: ["*"], environments: ["*"]}
Un binding si applica quando l'identità appartiene a uno dei suoi groups (o corrisponde a uno dei suoi subjects); un'azione è consentita se almeno un binding la concede. Vedi Ruoli e azioni.
Accedi#
- Interfaccia web: apri
https://manent.example.come accedi. I token restano solo in memoria, senza cookie; un ricaricamento della pagina ti fa riaccedere in silenzio finché dura la sessione del provider. -
CLI: manent non esegue il login da sé. Ottieni un token di accesso per l'audience
manentcon gli strumenti del provider (un device authorization grant, unoidc-agent, un portale aziendale) e salvalo neltoken_filedel client: -
CI: usa i token statici con ruoli propri.
Verifica#
{"subject": "oidc:alice", "method": "oidc", "groups": ["team-shop"], "auth_enabled": true,
"grants": [{"role": "deployer", "applications": ["shop*"], "environments": ["dev", "test", "staging"]}]}
| Sintomo | Causa probabile |
|---|---|
401 su ogni richiesta |
issuer errato (deve coincidere esattamente con iss, slash finale compreso) o audience errata. Decodifica il token e confronta. |
Accesso riuscito, ma 403 ovunque |
Il claim dei gruppi manca nel token di accesso o ha un altro nome: controlla groups_claim e i mapper. |
| L'interfaccia web dice che l'accesso non è configurato | Manca auth.oidc.ui.client_id. |
| L'interfaccia web dice che serve HTTPS | PKCE richiede la Web Crypto API del browser, disponibile solo in HTTPS o su localhost. |
Riferimento: Autenticazione, permessi e audit, Interfaccia web.