Skip to content

Scopes and claims

The scopes Authio understands, the claims each one adds to the ID token, the access token and UserInfo, and how to create scopes and claims of your own.

A scope is a permission an application asks for in the authorization request; a claim is a field inside a token. Scopes decide which claims Authio writes: email adds the address, roles adds the roles, offline_access adds a refresh token.

A client can only ask for the scopes enabled on it, listed on the client’s Access tab. Asking for one that is not enabled is refused with invalid_scope before anyone signs in.

Standard scopes

ScopeAssignmentWhat it adds
openidDefaultMakes the request OpenID Connect: an ID token is issued and UserInfo answers. Granted only when the request names it.
profileDefaultname, given_name, family_name, unique_name, preferred_username and updated_at
emailDefaultemail and email_verified
phoneOptionalphone_number and phone_number_verified
rolesDefaultThe role claims of the access token — see Roles and permissions
offline_accessOptionalA refresh token, on the grants that issue one
addressOptionalNothing: Authio keeps no postal address for users

Default and optional scopes

Every scope has an assignment. A Default scope enabled on the client is granted whether or not the request names it; an Optional one only when the request asks for it. openid is the exception: it is granted only when requested.

What was granted is in the token’s scope claim, separated by spaces. Read it first when a claim you expected is missing.

Scopes about a person — openid, profile, email, phone, address and offline_access — never reach a token issued to a machine with the client credentials grant.

openid is required by default

Clients start with Require OpenID Connect on, in the client’s Configuration: an authorization request without openid is refused with invalid_scope. Turn it off for an application that only needs an access token to call an API and has no use for an ID token.

ID token, access token and UserInfo

The three answer different questions, and Authio fills them differently:

AspectID tokenAccess tokenUserInfo
Meant forYour application, to learn who signed inYour API, as the credential of each callYour application, to read the person’s current data
audThe client’s client_idThe API named with resource, or the audience configured on the client—
Profile, email and phoneName, username, email and phone, with their verification flags, whenever openid was grantedThe claims of profile, email and phone, for each one grantedThe claims of profile, email and phone, for each one granted, read at the time of the call
RolesNeverWith the roles scopeNever
Organizationorg_id and org_aliasorg_id and org_alias—
Claim mappersWhen the mapper targets itWhen the mapper targets it—
LifetimeThe client’s session lifetimeThe client’s access token lifetime—
Never authorize an API call with the ID token. It describes who signed in, carries no roles and is addressed to your application, not to your API.

Access token claims

ClaimValue
issThe realm’s issuer, such as https://authio.api.hyperio.tech/realms/acme
subThe user’s ID in the realm
audThe API named with resource, or the audience configured on the client
azpThe client_id of the client the token was issued to
scopeThe granted scopes, separated by spaces
typBearer. ID tokens carry ID and refresh tokens Refresh.
iat, nbf, exp, jtiIssue time, validity window and unique ID
sidThe session the token belongs to
auth_timeWhen the person authenticated
amrHow they authenticated: pwd, otp, swk (passkey), user, mca, fed, plus mfa when two distinct factors were used
acr1 for one factor, 2 for several, 3 for several with a phishing-resistant credential
idpThe alias of the external provider, when the sign-in began at one
org_id, org_aliasThe organization of the sign-in — see Organizations
Access token payloadJSON
{
  "iss": "https://authio.api.hyperio.tech/realms/acme",
  "sub": "6f1c2e7a-4b8d-4f0e-9a51-3c2d7e8b9f10",
  "aud": "https://api.acme.com",
  "azp": "acme-web",
  "typ": "Bearer",
  "scope": "openid profile email offline_access",
  "sid": "0b7e4c2a-9d1f-4a6e-8c3b-5f2d1e9a7c40",
  "auth_time": 1791370800,
  "acr": "2",
  "amr": ["pwd", "otp", "mfa"],
  "email": "maria@acme.com",
  "email_verified": true,
  "name": "Maria Silva",
  "given_name": "Maria",
  "family_name": "Silva",
  "unique_name": "maria",
  "preferred_username": "maria",
  "updated_at": 1790000000,
  "iat": 1791370800,
  "nbf": 1791370800,
  "exp": 1791372600,
  "jti": "e5a8c1d4-7b2f-4c9e-a3d6-1f8b0e4c7a25"
}

UserInfo

UserInfo returns the person’s current data, read at the time of the call: a name changed or an email confirmed since sign-in shows up at once. Call it with the access token, by GET or POST.

RequestBash
curl https://authio.api.hyperio.tech/realms/acme/protocol/openid-connect/userinfo \
  -H "Authorization: Bearer $ACCESS_TOKEN"
  • sub is always present; profile, email and phone each add their claims when the token was granted them.
  • Empty values are left out.
  • A token without openid gets 403 with insufficient_scope; an invalid token, or one whose user is no longer active, gets 401 with invalid_token.

Custom scopes

Create scopes for your own APIs, such as invoices:read or reports.export, in Permissions › Global Scopes with New Scope — or exclusive to a realm or a client, from that record’s page. A scope exclusive to a client is enabled on it as soon as it is created. Scopes that belong to one API can also be declared on its resource server.

FieldRules
NameUp to 200 characters of printable ASCII, without spaces, quotes or backslashes. The standard scopes above, role_list, web-origins, acr and microprofile-jwt are reserved.
Consent descriptionUp to 500 characters, shown to the person on the consent screen when the client asks for consent.
ProtocolA classification: OpenID Connect, OAuth 2.0, Client Credentials or SAML. Scopes classified as SAML never enter a JWT.
AssignmentDefault or Optional, as described above.

A custom scope adds its name to the scope claim and nothing else; your API checks it there. To put data into the token, use a claim mapper.

Custom claims

Claim mappers add claims of your own to the tokens a client issues. Open the client’s Access tab, go to Claim mappers and add one rule per claim: its name, where its value comes from and which tokens receive it.

SourceValue
User propertyEmail, email confirmed, username, first name, last name, full name, phone, phone confirmed, account creation date or status
RolesThe names of the person’s roles, direct or through a group
GroupsThe names of the person’s active groups
Fixed valueA constant you type, up to 512 characters
  • Each rule writes to the access token, the ID token or both; at least one.
  • The claim name has up to 64 characters, starts with a letter or _, uses only letters, digits, _, : and -, and is unique among the client’s mappers.
  • Names the protocol writes are refused: iss, aud, exp, nbf, iat, jti, azp, nonce, typ, alg, kid, sub, scope, client_id, sid, acr, amr, idp, at_hash, c_hash and auth_time.
  • Mappers do not depend on scopes: an active mapper writes its claim on every token it targets. A source with several values, such as roles, is written as an array.

Before saving, the mapper screen previews the resulting token for a real user of the client. Claims added to a user directly, on the Permissions step of the user’s edit screen, go into that user’s access tokens.

Next steps