A client scope in Keycloak is a reusable bundle of protocol mappers and role restrictions that decides which claims and scopes land in the tokens a client receives. Default client scopes always apply; optional ones apply only when the application asks for them in the OAuth scope parameter, while roles state what a user may do. The Keycloak Server Administration Guide describes it as “a shared client configuration in an entity called a client scope” that “configures protocol mappers and role scope mappings for multiple clients.”
So when you open a client in the admin console and meet the Client scopes tab, you are looking at the place where, in the guide’s words, “linking between a client scope and the client is configured” (source). This post shows what a client scope adds to a real token, walks through every built-in scope in Keycloak 26, explains default and optional scopes, the dedicated scope, Full scope allowed and the Evaluate tab, and then compares client scopes with plain OAuth scope strings and with roles.
Key takeaways
- A client scope holds protocol mappers, which put claims in tokens, and role scope mappings, which limit the roles that can appear.
- Default client scopes apply “regardless of the value used for the scope parameter,” and optional ones apply when requested.
- Full scope allowed is deprecated: switch it off and list the roles each client may see.
- The Evaluate sub-tab simulates a client’s tokens for a chosen user.
What is a client scope in Keycloak?
A client scope is a named container with two things inside it. The first is a set of protocol mappers, which are rules that read something (a user attribute, a role, a fixed value) and write it into a token claim. The second is a set of role scope mappings, which limit the roles that may appear in tokens issued through that scope. The protocol mappers section of the Keycloak guide covers the mapper types in detail.
You create a client scope once, in the realm’s Client scopes menu, and then “link this shared client scope to every client that should apply this shared configuration” (source). When a token is issued, the client “will inherit Protocol Mappers and Role Scope Mappings that are defined on the client scope” for each scope that applies to the request (source). That is why you can add a department claim to twenty applications by editing one client scope instead of twenty clients.
Client scopes are also how Keycloak supports the OAuth 2.0 scope parameter. The guide puts it this way: “Client applications use this parameter to request claims or roles in the access token, depending on the requirement of the application” (source). If you want a refresher on the OAuth side of that, our post on OAuth scopes explained covers it.
What a client scope looks like in a decoded token
The easiest way to see client scopes is to decode an access token and ask which scope put each claim there. Here is a trimmed example of an access token for a client called dashboard, requested with scope=openid phone, for a user who holds the realm role editor and the client role viewer on dashboard. The values are made up, but the claim names match the mappers defined for the built-in scopes in Keycloak’s OIDCLoginProtocolFactory source for 26.0.0.
{
"iss": "https://auth.example.com/realms/acme",
"sub": "8f2c4b1e-6d3a-4c9e-9b7a-2e5f1d0c8a44",
"auth_time": 1792310400,
"acr": "1",
"aud": ["dashboard"],
"azp": "dashboard",
"scope": "openid email phone profile",
"allowed-origins": ["https://dashboard.example.com"],
"realm_access": { "roles": ["editor", "offline_access"] },
"resource_access": { "dashboard": { "roles": ["viewer"] } },
"name": "Ada Lovelace",
"preferred_username": "ada",
"given_name": "Ada",
"family_name": "Lovelace",
"email": "ada@example.com",
"email_verified": true,
"phone_number": "+1 555 0100",
"phone_number_verified": false
}
Reading it scope by scope:
subandauth_timecome from thebasicscope (upgrading guide).acrcomes from theacrscope (step-up section).realm_access,resource_accessand theaudvalue come from therolesscope, whose mappers “add the roles of the user to the access token and add audiences for clients that have at least one client role” (source).allowed-originscomes from theweb-originsscope, which the same section says adds “allowed web origins to the access token allowed-origins claim.”name,preferred_username,given_nameandfamily_namecome fromprofile, andemailandemail_verifiedcome fromemail, following the claim lists in OpenID Connect Core, section 5.4.phone_numberandphone_number_verifiedcome fromphone, which is optional and only applies because the request asked forphone(source).
Notice that the scope claim lists email, phone and profile but not roles, web-origins, basic or acr, even though all of those ran. That is the Include in token scope switch at work: the guide says some built-in scopes have it disabled, so “they are not included in the scope claim even if they are applied” (source). You can paste any token of your own into the Skycloak JWT Token Analyzer to read it the same way. If you are not sure which token you are looking at, our post on ID tokens vs access tokens explains the difference.
The built-in client scopes in Keycloak 26
The guide says “each realm has a set of pre-defined built-in client scopes in the menu,” which is Client scopes in the left-hand menu of the admin console (source). It describes them under the OpenID Connect protocol, and the upgrading guide covers basic, the newest one. The table below shows what each one adds and how it is linked to new clients. The last two columns come from the code that creates these scopes in a new realm, where each scope is registered as default or optional and its Include in token scope flag is set (OIDCLoginProtocolFactory, Keycloak 26.0.0); offline_access is linked as optional “by default,” according to the offline access section.
| Client scope | What it adds | Linked to new clients as | In the scope claim? |
|---|---|---|---|
profile |
Standard profile claims such as name, given_name, family_name, preferred_username, locale |
Default | Yes |
email |
email and email_verified |
Default | Yes |
roles |
realm_access.roles, resource_access, and audiences for clients where the user has a client role |
Default | No |
web-origins |
The allowed-origins claim used for CORS |
Default | No |
acr |
The acr claim (authentication context class reference) used for step-up authentication |
Default | No |
basic |
sub and auth_time |
Default | No |
offline_access |
Lets the client obtain an offline token, a refresh token that outlives the login session | Optional | Yes |
microprofile-jwt |
upn and groups claims for the MicroProfile JWT specification |
Optional | Yes |
address |
The OpenID Connect address claim |
Optional | Yes |
phone |
phone_number and phone_number_verified |
Optional | Yes |
organization |
The organization claim with the user’s organization membership |
Optional | Yes |
A few notes on the less obvious rows, each from the Keycloak documentation:
profile,email,addressandphoneare defined by OpenID Connect itself. OpenID Connect Core, section 5.4 lists the claims each one requests, and Keycloak’s versions of these scopes “have protocol mappers defined” that “correspond to the claims defined in the OpenID Connect specification” (source).rolesandweb-originsare Keycloak’s own. The guide saysrolesis “not added automatically to the scope claim in the access token” and carries the mappers that add the user’s roles and “add audiences for clients that have at least one client role” (source).basicarrived in Keycloak 25. The upgrading guide says it “is added as a realm default client scope” and contains mappers forsubandauth_time.acrholds the “acr loa level protocol mapper” and is a realm default scope, according to the step-up authentication section.offline_accessonly works if the user also holds the realm role: the offline access section says “users must have the role mapping for the realm-level offline_access role,” that the client must have the scope linked as optional, “which is done by default,” and that the client requests it withscope=offline_access.microprofile-jwt“defines a user property mapper for the upn claim and a realm role mapper for the groups claim” (source).organizationis “a built-in optional client scope at the realm” that defines the Organization Membership mapper. You can request it asorganization,organization:acmefor a specific organization, ororganization:*for all of them (source).
Two of these settings are realm-wide defaults rather than fixed rules. Realm default client scopes decide which scopes are linked to newly created clients and whether as default or optional. The guide says you set this in the Assigned type column of the Client scopes list, and that these sets are “automatically linked to newly created clients.” Because that wording covers new clients, check an existing client’s own Client scopes tab to see what it really uses.
Default vs optional client scopes
The guide describes “two ways of linking between the client scope and the client,” default and optional (source), and the difference between them is the most useful thing to understand about this feature.
Default client scopes are always applied. The Keycloak guide says their mappers and role scope mappings “are always applied, regardless of the value used for the scope parameter in the OpenID Connect authorization request.” Your application does not have to ask for them, and it cannot opt out of them by leaving them out of the request.
Optional client scopes are applied “only when requested by the scope parameter in the OpenID Connect authorization request.” The guide’s own example has profile and email as default and phone and address as optional. A request with scope=openid phone gets the mappers from profile, email and phone, but not address. The word openid is, in the guide’s words, “the meta-value used for all OpenID Connect requests.”
This split lets you keep the everyday token small and let an application ask for more only when it needs it. The guide’s audience section shows the pattern: a client that sends scope=service1-scope service2-scope, where each scope holds an Audience mapper, gets "aud": [ "service1", "service2" ]. The reproducible example below does the same with one API.
Include in token scope
Each client scope has an Include in token scope switch. When it is on, the scope’s name is added to the scope claim of the access token and to the token and introspection responses. When it is off, the scope still runs its mappers but its name does not appear (source). That is why roles, web-origins, basic and acr shaped the example token above without showing up in its scope claim. If your API authorizes requests by checking the scope claim, make sure your own client scopes have this switch on.
Client scope vs OAuth scope string vs role
Three different things share the word “scope” or get confused with it, and most questions about this feature come from mixing them up.
An OAuth scope string is a word in the scope request parameter. RFC 6749, section 3.3 defines it as “a list of space-delimited, case-sensitive strings” whose meaning is “defined by the authorization server.” OAuth.net describes scope as “a mechanism in OAuth 2.0 to limit an application’s access to a user’s account.” The specification also allows the server to “fully or partially ignore the scope requested by the client,” so a string on its own guarantees nothing.
A client scope is how Keycloak gives a scope string a meaning. In the guide’s own example, a request with scope=openid phone picks up “phone, an optional client scope requested by the scope parameter” (source), so a request for api.read applies the optional client scope of that name when one is linked to the client. The string is the request, and the client scope is the configuration that answers it.
A role is a permission such as editor or billing-admin that is assigned to a user directly, through a group, or to a client’s service account. A role does nothing to a token by itself. The guide says the roles added to a token are “an intersection of” the roles assigned to the user and the “role scope mappings of the roles that the client is permitted to access,” and that role protocol mappers (by default, those in the built-in roles client scope) write them into the token (source).
| OAuth scope string | Client scope | Role | |
|---|---|---|---|
| What it is | A word in the scope parameter |
A Keycloak config object with mappers and role limits | A permission held by a user or service account |
| Who sets it | The application, at request time | An admin, on the realm and the client | An admin, on users, groups or service accounts |
| What it controls | Which optional client scopes to apply | Which claims and roles go into the token | What the user is allowed to do |
| Where it shows in a token | The scope claim |
The claims its mappers add | realm_access.roles and resource_access |
| Admin console path | Set by the application, not the console | Client scopes, or Clients, your client, Client scopes | Realm roles, or Clients, your client, Roles |
| Defined by | RFC 6749 | Keycloak | Keycloak |
Put in one sentence, the application asks with a scope string, the client scope decides what that request puts in the token, and the role is the fact about the user that your API finally checks.
The dedicated scope and Full scope allowed
When you open a client’s Client scopes tab, the first row is always a scope named after the client, such as dashboard-dedicated. The guide calls this the dedicated client scope: it holds “the protocol mappers and role scope mappings, which are linked directly to the client itself.” You cannot unlink it or share it with another client, and in the Admin REST API it does not exist as a separate object, because it is “just an abstraction for the admin console UI.” Use it for mappers that only one client needs, and use a shared client scope for anything two or more clients need.
The dedicated scope’s Scope tab is also where you find Full scope allowed. The guide says “clients are created with Full Scope Allowed enabled, which causes every access token to contain all roles held by the authenticated user” (source). The role scope mappings section of the current guide now says this switch “is deprecated and will be removed in a future release,” and recommends that you “disable Full Scope Allowed on every client and explicitly configure the required role scope mappings instead.” It also describes a client policy with a Full Scope Disabled executor that enforces this for a whole realm (source).
Turning it off has two benefits. Tokens carry fewer role claims, which helps when tokens grow large enough to be rejected by a proxy, as our post on the Keycloak 431 token too large error explains. Tokens also carry only the roles that matter to that client; the guide warns that leaving it on “unnecessarily widens the blast radius if a token is compromised” (source).
The admin console path in Keycloak 26 is Clients, then your client, then Client scopes, then the dashboard-dedicated link, then the Scope tab. That is the procedure in the role scope mappings section, which says to “toggle Full Scope Allowed to OFF and declare the specific roles you want in each client.”
Talk through your identity setup with us
Book a demo and we will walk you through Skycloak with the sign-in, SSO and migration questions your team is working on.
How to preview a token with the Evaluate tab
You do not have to deploy an application to see what a client scope does. The Evaluating client scopes procedure in the guide works like this:
- Open Clients, choose your client, and open the Client scopes tab.
- Open the Evaluate sub-tab.
- Pick the optional client scopes you want to apply.
- Pick a user and look at the access token, ID token or UserInfo response the guide says it simulates “for a particular selected user.”
The guide says the Evaluate tab also shows “the value of the scope parameter” your application needs to send, which saves guessing at the exact string. It also shows “the effective protocol mappers (that is the protocol mappers defined on the client itself as well as inherited from the linked client scopes) and the effective role scope mappings.” When a claim you expected is missing, this is the fastest place to find out which scope should have added it. Our post on why a custom attribute is not in the token walks through that debugging in more detail.
On Skycloak, an application’s Mappers tab shows the mappers you added and, below them, the ones it inherits from client scopes, which are read-only there because they are shared (Skycloak applications docs).
Creating and linking a client scope with kcadm or the Admin API
In the admin console, choose Client scopes in the left menu, then Create client scope, give it a name and protocol (OpenID Connect), and save. Add mappers on its Mappers tab. Then open the client, go to Client scopes, choose Add client scope, select yours and pick Default or Optional.
The same steps with the Admin CLI (kcadm.sh) look like this. The Admin CLI section of the guide captures a new object’s ID with create ... -i, and says create, get, update and delete “map to the HTTP verbs POST, GET, PUT, and DELETE.” The last call is a PUT to the Admin REST API path /admin/realms/{realm}/clients/{client-uuid}/optional-client-scopes/{clientScopeId}. That path has no GET, so the call needs -n, which the guide says “performs a put command without first running a get command.”
# Log in to the admin CLI
kcadm.sh config credentials --server https://auth.example.com \
--realm master --user admin
# Create an OIDC client scope that shows up in the scope claim
SID=$(kcadm.sh create client-scopes -r acme -i \
-s name=api.read \
-s protocol=openid-connect \
-s 'attributes."include.in.token.scope"=true')
# Add an Audience mapper that puts orders-api in the aud claim
kcadm.sh create client-scopes/$SID/protocol-mappers/models -r acme \
-s name=api-audience \
-s protocol=openid-connect \
-s protocolMapper=oidc-audience-mapper \
-s 'config."included.client.audience"=orders-api' \
-s 'config."access.token.claim"=true'
# Find the client's internal ID and link the scope as optional
CID=$(kcadm.sh get clients -r acme -q clientId=dashboard --fields id --format csv --noquotes)
kcadm.sh update clients/$CID/optional-client-scopes/$SID -r acme -n
To link it as a default scope instead, use default-client-scopes in the last path, which the REST API documents as its own PUT. The reproducible example below shows what a token request returns once the scope is linked. For how an API reads and checks the tokens it receives, see our guide to Keycloak token validation for APIs.
Roles in Keycloak: modeling permissions
The second half of the picture is roles. Keycloak’s roles and groups documentation covers assigning them to users and groups. There are three kinds.
Realm roles are defined once for the whole realm, which the guide calls “a namespace for defining your roles.” By default they appear in the token under realm_access.roles (source), so a role like admin or billing-viewer is a good fit when the permission spans several services.
Client roles are “namespaces dedicated to clients” and by default appear under resource_access, keyed by the client ID (for example resource_access.dashboard.roles), according to the same section. A role like viewer on the dashboard client only means something inside that application, which keeps the realm-wide list of roles clean.
Composite roles contain other roles. A composite superadmin might include billing-viewer, user-manager and report-exporter, which saves repeated assignments. The guide says the inheritance “is recursive” and adds “we recommend that composite roles are not overused” (source).
Roles answer “what may this user do?” and nothing else. Whether a role shows up in a given token depends on a role mapper (by default, the ones in the roles client scope) and on the client’s role scope mappings, which is why the two features work together. On Skycloak, an application’s Mappers tab also offers a Role mapper that puts the user’s realm roles in the token (Skycloak applications docs), and our role-based access control page covers how roles are managed. When simple role checks are not enough, our posts on fine-grained authorization in Keycloak and Keycloak authorization services policy types cover the next layer.
A worked example: the api.read scope and the editor role
Suppose a single-page app called dashboard calls an API called orders-api, and some users may edit orders while others may only read them.
- The
editorrealm role is assigned to users who may edit. It appears asrealm_access.rolescontainingeditor, andorders-apiis written to allow write calls only when it is there. - The
api.readoptional client scope holds an Audience mapper fororders-api, has Include in token scope on, and is linked todashboardas optional. - The
readerrealm role is assigned to every user who may read. - Full scope allowed is off on
dashboard, and its role scope mappings list onlyeditorandreader, so other realm roles stay out of this client’s tokens.
When the app requests scope=openid api.read, the token gains orders-api in aud and api.read in scope. A user without the editor role still gets the scope, but not the role, so an API written this way lets them read and refuses writes. The client scope shaped the token, and the role decided the outcome.
Reproduce the worked example
You can rebuild this example on a test server and check each claim yourself. The steps below follow the Keycloak 26.8.1 Server Administration Guide and Admin REST API, and use only the Admin CLI and the token endpoint. They use the resource owner password grant, which the guide calls Direct Access Grants, because it fits in one curl call; keep that switch off on any real client, where the application would log in through the browser instead.
First, create the realm, the two clients, the two roles and two test users. ada holds editor and reader, and bob holds only reader.
kcadm.sh create realms -s realm=acme -s enabled=true
kcadm.sh create clients -r acme -s clientId=orders-api -s enabled=true
CID=$(kcadm.sh create clients -r acme -i \
-s clientId=dashboard -s enabled=true \
-s publicClient=true -s directAccessGrantsEnabled=true \
-s fullScopeAllowed=false)
kcadm.sh create roles -r acme -s name=editor
kcadm.sh create roles -r acme -s name=reader
# Role scope mappings: the only realm roles dashboard's tokens may carry
for ROLE in editor reader; do
kcadm.sh get roles/$ROLE -r acme | jq -s . \
| kcadm.sh create clients/$CID/scope-mappings/realm -r acme -f -
done
for U in ada bob; do
kcadm.sh create users -r acme -s username=$U -s enabled=true \
-s email=$U@example.com -s emailVerified=true \
-s firstName=$U -s lastName=Test
kcadm.sh set-password -r acme --username $U --new-password 'change-me-1'
kcadm.sh add-roles -r acme --uusername $U --rolename reader
done
kcadm.sh add-roles -r acme --uusername ada --rolename editor
The scope mappings loop calls the documented POST to scope-mappings/realm, which takes a list of roles. Next, run the three commands from the kcadm section above to create api.read, add its Audience mapper and link it to dashboard as optional. Then request a token for each user, once without the optional scope and once with it, and print the claims that matter:
TOKEN_URL=https://auth.example.com/realms/acme/protocol/openid-connect/token
token() {
curl -s "$TOKEN_URL" -d grant_type=password -d client_id=dashboard \
-d username="$1" -d password='change-me-1' -d scope="$2" \
| jq -r .access_token \
| jq -R 'split(".")[1] | gsub("-";"+") | gsub("_";"/") | @base64d | fromjson
| {aud, scope, roles: .realm_access.roles}'
}
token ada "openid"
token ada "openid api.read"
token bob "openid api.read"
According to the guide, this is what each call should show. With scope=openid, api.read is not applied, because an optional scope applies “only when requested by the scope parameter” (source), so orders-api is missing from aud and api.read from scope. With scope=openid api.read, the Audience mapper adds orders-api to aud, in the same way as the guide’s "aud": [ "service1", "service2" ] example (source), and api.read appears in scope because Include in token scope is on. In every call, roles holds only roles from editor and reader, because with Full scope allowed off the token carries the intersection of the user’s roles and the client’s role scope mappings (source): ["editor", "reader"] for ada (in either order) and ["reader"] for bob. Both users get the same scope and audience, and only the role list differs, which is the point of the example. If your output does not match, open dashboard, then Client scopes, then Evaluate, pick the same user and optional scope, and compare.
Frequently asked questions
Why is my requested scope ignored?
Check four things in order. First, the client scope must be linked to this client as optional (or default) on the client’s Client scopes tab, because the guide describes default and optional scopes as the two ways a client scope is linked to a client (source). Second, if the client scope has role scope mappings, the user must hold at least one of those roles; the guide says that otherwise “no protocol mappers or role scope mappings will be used” and the scope “will not appear in the scope value in the token” (source). Third, if the mappers ran but the name is missing from the scope claim, the scope’s Include in token scope switch is off (source). Fourth, tokens are built when they are issued, so request a new token after any change. The Evaluate tab, run for the same user and optional scopes, shows the effective mappers and role scope mappings, which narrows down which of these applies.
Why does client_credentials drop my scopes?
The client credentials grant has no authorization request, so the scope parameter goes in the body of the POST to the token endpoint alongside grant_type=client_credentials, as RFC 6749, section 4.4.2 defines it. Optional scopes apply “only when requested” (source), so one missing from that body is not applied. The Keycloak guide makes the same point for offline tokens, saying service accounts support them “if you include scope=offline_access in the authentication request body” (source). The guide says this grant “creates a token based on the metadata and permissions of a service account associated with the client” (source), and that for a service account “the service account roles are used” (source). So a client scope with role scope mappings only applies if the service account holds a matching role (source). The guide also lists the client credentials grant as an exception to returning refresh tokens by default (source), which our post on access tokens vs refresh tokens puts in context.
How do I add a scope or claim to only one client?
If only one client will ever need the mapper, add it to that client’s dedicated scope, which the guide says is “useful just for protocol mappers and role scope mappings, which are specific to a single client” (source): Clients, your client, Client scopes, the your-client-dedicated link, then its Mappers tab. If you want a named scope the application can request, create a client scope and link it to that one client only, as optional or default. Avoid setting it as a realm default client scope, because realm defaults are “automatically linked to newly created clients” (source).
Why are realm_access and resource_access in every token?
They come from the built-in roles client scope, whose mappers add the user’s roles (source) and which is linked as a default scope on new clients, combined with Full scope allowed being on, which puts “all roles held by the authenticated user” in every access token (source). A Keycloak community discussion on exactly this question has a reply that points to the client’s scopes tab, each scope’s mappers and the Evaluate sub-tab, and suggests disabling Full scope allowed. If your client never needs roles, you can also unlink the roles scope, since the guide says that “when a client is created, you can unlink the default client scopes, if needed” (source).
What to do next
Start by opening one of your clients, going to Client scopes, then Evaluate, and generating a token for a real user. Compare what you see with the table of built-in scopes above, turn off Full scope allowed and add only the roles that client needs, and move any client-specific mappers into its dedicated scope. Then create named optional scopes, with an Audience mapper, for each API your applications call.
To check the result, paste a token into the Skycloak JWT Token Analyzer and see which claims each client scope added. When you want the same realm without running Keycloak yourself, you can try it on a free Skycloak trial.
Sources
All retrieved 17 October 2026. The Keycloak guide pages were at version 26.8.1 when retrieved.
- Keycloak, “Server Administration Guide,” section “Client scopes” (protocol, Include in token scope, linking, dedicated client scope, evaluating, permissions, realm default client scopes), https://www.keycloak.org/docs/latest/server_admin/#_client_scopes
- Keycloak, “Server Administration Guide,” sections “Role scope mappings” and “Enforcing Full Scope Allowed to be disabled,” https://www.keycloak.org/docs/latest/server_admin/#_role_scope_mappings
- Keycloak, “Server Administration Guide,” sections “Role mappings in the token” and “Audience support,” https://www.keycloak.org/docs/latest/server_admin/#_oidc_token_role_mappings
- Keycloak, “Server Administration Guide,” sections “Offline access,” “Creating a browser login flow with step-up mechanism,” “Mapping organization claims” and “Converting a role to a composite role,” https://www.keycloak.org/docs/latest/server_admin/#_offline-access
- Keycloak, “Server Administration Guide,” sections “OIDC auth flows” (Direct Access Grants, client credentials grant, refresh token grant) and “Admin CLI,” https://www.keycloak.org/docs/latest/server_admin/#_oidc-auth-flows-direct
- Keycloak, “Upgrading Guide,” section “New default client scope basic” (migrating to 25.0.0), https://www.keycloak.org/docs/latest/upgrading/#new-default-client-scope-basic
- Keycloak, “Admin REST API,” client scope linking and scope mapping endpoints, https://www.keycloak.org/docs-api/latest/rest-api/index.html
- Keycloak project source,
OIDCLoginProtocolFactory.javaat tag 26.0.0 (built-in client scopes and their default or optional links), https://github.com/keycloak/keycloak/blob/26.0.0/services/src/main/java/org/keycloak/protocol/oidc/OIDCLoginProtocolFactory.java - Keycloak GitHub Discussions, “Understanding Keycloak’s default client scopes” (#37804), https://github.com/keycloak/keycloak/discussions/37804
- IETF, “The OAuth 2.0 Authorization Framework” (RFC 6749), sections 3.3 and 4.4.2, https://datatracker.ietf.org/doc/html/rfc6749
- OpenID Foundation, “OpenID Connect Core 1.0,” section 5.4 “Requesting Claims using Scope Values,” https://openid.net/specs/openid-connect-core-1_0.html#ScopeClaims
- OAuth.net, “OAuth 2.0 Scopes,” https://oauth.net/2/scope/
