Scopes
When an app asks a person to sign in, it also says what it wants to know: their name, their email address, the roles they hold. Each of those is requested by name. The name is a scope, and it is the vocabulary an app and a person use to agree on what is shared.
In words: A client asks for scopes. They are sorted against the default and optional scopes the client has, a consent screen may let the person choose among the optional ones, and what was allowed decides the claims in the access token, the ID token and the UserInfo answer.
What a scope does
A scope is a name with three jobs.
- It says what the client wants. The client sends
scope=openid email, and Odudu reads each word. - It adds claims.
emailadds the person's address.profileadds their name.rolesandgroupsadd what they hold. Each scope says whether its claims go in the ID token, the access token or both, withinclude_in_id_tokenandinclude_in_access_token. - It is what a person approves. On the consent screen each scope is shown by its
consent_text, in the order you give it withdisplay_order.
openid is the scope that turns a request into a sign-in. Without it the client gets no ID token.
Default and optional
A tenant defines its scopes. A client does not get all of them. Each client is assigned the ones it may ask for, and each assignment is either default or optional:
- A default scope is given whenever the client asks. On the consent screen it is listed, but the person cannot untick it, because an app without
openidcannot work at all. - An optional scope is the person's choice. It shows a tick box. Next time, the box remembers what they allowed.
A scope can also be marked to be given to every new client, as default or as optional, through default_client_assignment.
A client that asks for a scope it was not assigned is refused with invalid_scope.
The built-in scopes
Every tenant starts with eight scopes: openid, profile, email, address, phone, roles, groups and offline_access. You can edit them, for example to give profile a consent text. You can also delete them, except openid, which every client's sign-in depends on. Deleting one takes it off every client that carries it and unmaps every role mapped to it, which is why the console counts both first and asks you to type the scope's name, and why the admin API refuses to delete a built-in scope until the request names it again.
Whether a scope is built in is decided by its name alone. A scope you create yourself under one of those eight names counts as built in, so deleting it needs the same confirmation, and a restore will not create a name that already exists.
A deleted built-in scope can be created again. The restore makes each missing one with the settings a new tenant is given, leaves any that exist alone, and does not bring back the client assignments or role mappings the deletion removed. You do it from the scopes list in the console, with POST /admin/tenants/{tenant}/scopes/restore-builtins in the admin API, or with odudu seed restore-scopes --tenant <name>. Doing it twice is harmless.
Where a scope's claims come from
A scope's claims are built by claim mappers. If you bind none to a scope, every mapper that declares that scope runs, and the console shows them ticked and greyed on the scope's Claim mappers tab. Bind one and only the bound mappers run.
Roles reach a token through a scope
A role is not a claim on its own. You map it to a scope, and it reaches a token only when that scope was granted. A person with the reviewer role who signs in without the scope that carries it gets a token that does not mention it. Roles and groups explains how a person comes to hold a role.
A client's Include all roles in tokens setting (full_scope_allowed in the admin API) changes that. Off, the default, a token carries only the roles mapped to the granted scopes. On, the roles scope carries every role the person holds.
The roles claim itself comes from the roles scope, so a client that is not granted roles gets no roles claim. On a scope's Roles tab, "No roles mapped" means the scope adds no roles for a client with Include all roles in tokens off.
The roles and groups scopes ship with include_in_id_token off: an ID token travels through the browser, and a full list of roles has no business there.
What UserInfo does with a request
An app can name the claims it wants from the UserInfo endpoint in a claims request. Odudu then returns exactly those, plus sub, even when the granted scope would have allowed more. A client that says what it needs gets only that. Details are in the UserInfo endpoint reference.
Working with scopes
- List the claims your app really needs, and nothing else.
- Find or create a scope for each. The scopes operations create, change and delete them.
- Assign each to the client as default if the app cannot work without it, and as optional if the person may refuse.
- Give optional and sensitive scopes a clear
consent_text, written for the person who reads it. - Request them when you start a sign-in, as in Sign a user in.
Where to go next
- Consent and audit shows when the screen appears.
- Tokens shows where the granted claims end up.