Scopes and claims
Every scope auth.codai.ro issues, what the user sees on the consent screen, which claims and resources each one unlocks.
Request scopes space-separated in the scope parameter of the authorize request. The consent screen shows the user the description in the second column, verbatim. Standard OIDC scopes return claims in the ID token and at GET /me; codai scopes are resource scopes — they carry no claims, they decide what the access token may do at https://ai.codai.ro.
Scopes
| Scope | Consent screen text | Unlocks |
|---|---|---|
openid | Verify your codai identity | Required. Claims sub, role, sid. |
profile | See your name and profile picture | Claims name, picture. |
email | See your email address | Claims email, email_verified. |
inference | Run AI inference through your codai account | Lets the access token mint a gateway key at /connect/key. Resource https://ai.codai.ro/v1. |
keys:manage | Create and manage codai API keys on your behalf | Also entitles /connect/key. Request it when your app manages the key's lifecycle rather than only using it. |
usage:read | Read your codai usage statistics | Resource scope on https://ai.codai.ro/v1. |
subscriptions:read | Read your codai subscription plan | Resource scope on https://ai.codai.ro/v1. |
mcp | Use codai tools and memory from an MCP client | Only against resource https://ai.codai.ro/mcp; the access token becomes an RS256 JWT the gateway verifies locally. |
offline_access | Stay signed in on this device | A rotating refresh token — issued only if the client also has the refresh_token grant. |
For the connect flow the canonical request is openid email profile inference keys:manage. Ask for what you use; the user reads the list.
Resources and token format
auth.codai.ro implements RFC 8707 resource indicators. The resource parameter (default https://ai.codai.ro/v1) selects which resource server the access token is for; a token is scoped to the intersection of what you requested and what that resource accepts.
| Resource | Scopes it accepts | Access token |
|---|---|---|
https://ai.codai.ro/v1 (default) | inference keys:manage usage:read subscriptions:read | Opaque, 1 h |
https://ai.codai.ro/mcp | mcp | RS256 JWT, 1 h, aud = the resource, carries role |
You do not have to think about this for the connect flow — omit resource and you get the default.
Claims
Claims live in the ID token and are returned by GET /me with a valid access token.
| Claim | From scope | Value |
|---|---|---|
sub | openid | The user's stable codai id (UUID). Key every record you store on this, never on email. |
role | openid | The account role, e.g. user. Present in the ID token even when an access token is issued alongside — codai does not strip non-standard claims. Also inside MCP JWT access tokens. |
sid | openid | The IdP session id. Match it against the sid in a back-channel logout_token to end the right local session. |
name | profile | Display name. |
picture | profile | Avatar URL. |
email | email | Email address. |
email_verified | email | Boolean. |
acr, amr | — (always) | How the user authenticated this session. |
Authentication context
The IdP stamps every ID token with how the user signed in:
| Method | amr | acr |
|---|---|---|
| Password | ["pwd"] | urn:codai:acr:pwd |
| Password + 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 |
To require a level, send acr_values on the authorize request — urn:codai:acr:mfa for a second factor, urn:codai:acr:passkey for a passkey. The IdP re-prompts when the current session's method is weaker or its login is older than 10 minutes, then returns the achieved acr. Check it in the ID token; do not assume.
What a token does not carry
- No organisation or team claim — orgs are a shared-sessions concept on the gateway, queried with the gateway key.
- No plan or billing information — that is behind
subscriptions:readat the gateway, not in the ID token. - No API key. The key comes only from
/connect/key, only once.