Scope-uri și claim-uri
Fiecare scope emis de auth.codai.ro, ce vede utilizatorul pe ecranul de consimțământ, ce claim-uri și resurse deblochează fiecare.
Ceri scope-urile separate prin spațiu în parametrul scope al cererii de autorizare. Ecranul de consimțământ îi arată utilizatorului descrierea din a doua coloană, cuvânt cu cuvânt. Scope-urile OIDC standard returnează claim-uri în ID token și la GET /me; scope-urile codai sunt scope-uri de resursă — nu poartă claim-uri, ci decid ce poate face access token-ul la https://ai.codai.ro.
Scope-uri
| Scope | Text pe ecranul de consimțământ (EN) | Deblochează |
|---|---|---|
openid | Verify your codai identity | Obligatoriu. Claim-urile sub, role, sid. |
profile | See your name and profile picture | Claim-urile name, picture. |
email | See your email address | Claim-urile email, email_verified. |
inference | Run AI inference through your codai account | Permite access token-ului să emită o cheie de gateway la /connect/key. Resursa https://ai.codai.ro/v1. |
keys:manage | Create and manage codai API keys on your behalf | Dă și el dreptul la /connect/key. Îl ceri când aplicația ta gestionează ciclul de viață al cheii, nu doar o folosește. |
usage:read | Read your codai usage statistics | Scope de resursă pe https://ai.codai.ro/v1. |
subscriptions:read | Read your codai subscription plan | Scope de resursă pe https://ai.codai.ro/v1. |
mcp | Use codai tools and memory from an MCP client | Doar pe resursa https://ai.codai.ro/mcp; access token-ul devine un JWT RS256 pe care gateway-ul îl verifică local. |
offline_access | Stay signed in on this device | Un refresh token cu rotație — emis doar dacă clientul are și grant-ul refresh_token. |
Pentru fluxul de conectare, cererea canonică este openid email profile inference keys:manage. Cere doar ce folosești; utilizatorul citește lista.
Resurse și formatul token-ului
auth.codai.ro implementează indicatorii de resursă RFC 8707. Parametrul resource (implicit https://ai.codai.ro/v1) alege pentru care resource server este access token-ul; un token este limitat la intersecția dintre ce ai cerut și ce acceptă acea resursă.
| Resursă | Scope-uri acceptate | Access token |
|---|---|---|
https://ai.codai.ro/v1 (implicit) | inference keys:manage usage:read subscriptions:read | Opac, 1 h |
https://ai.codai.ro/mcp | mcp | JWT RS256, 1 h, aud = resursa, poartă role |
Nu trebuie să te gândești la asta pentru fluxul de conectare — omiți resource și primești valoarea implicită.
Claim-uri
Claim-urile stau în ID token și sunt returnate de GET /me cu un access token valid.
| Claim | Din scope-ul | Valoare |
|---|---|---|
sub | openid | Id-ul codai stabil al utilizatorului (UUID). Cheia fiecărei înregistrări pe care o stochezi e acesta, niciodată email. |
role | openid | Rolul contului, de ex. user. Prezent în ID token chiar și când se emite un access token alături — codai nu elimină claim-urile nestandard. Și în interiorul access token-urilor JWT pentru MCP. |
sid | openid | Id-ul sesiunii pe IdP. Îl potrivești cu sid dintr-un logout_token de back-channel pentru a încheia sesiunea locală corectă. |
name | profile | Numele afișat. |
picture | profile | URL-ul avatarului. |
email | email | Adresa de email. |
email_verified | email | Boolean. |
acr, amr | — (întotdeauna) | Cum s-a autentificat utilizatorul în această sesiune. |
Contextul de autentificare
IdP-ul marchează fiecare ID token cu felul în care s-a autentificat utilizatorul:
| Metodă | amr | acr |
|---|---|---|
| Parolă | ["pwd"] | urn:codai:acr:pwd |
| Parolă + TOTP | ["pwd", "otp"] | urn:codai:acr:mfa |
| Passkey | ["webauthn"] | urn:codai:acr:passkey |
| Magic link | ["email"] | urn:codai:acr:pwd |
["google"] | urn:codai:acr:pwd |
Pentru a impune un nivel, trimiți acr_values în cererea de autorizare — urn:codai:acr:mfa pentru un al doilea factor, urn:codai:acr:passkey pentru un passkey. IdP-ul cere din nou autentificarea când metoda sesiunii curente este mai slabă sau login-ul ei este mai vechi de 10 minute, apoi returnează acr-ul atins. Îl verifici în ID token; nu presupui.
Ce nu poartă un token
- Niciun claim de organizație sau echipă — organizațiile sunt un concept de sesiuni partajate pe gateway, interogat cu cheia de gateway.
- Nicio informație despre plan sau facturare — asta e în spatele
subscriptions:readla gateway, nu în ID token. - Nicio cheie API. Cheia vine doar de la
/connect/key, o singură dată.