Skip to content

Client Scopes

A client scope is a named, reusable bundle of mappers — and optionally audience or resource restrictions. It lets you define a set of claims once and attach it to multiple clients. Instead of configuring the same mappers on every client individually, you configure them once on a scope and assign the scope to many clients.

Think of a client scope as a named package that says: “when this scope is requested, add these claims to the token.”

Client scopes come in two types:

Default scopes are always included in every token issued by the client, regardless of what the application requests. The client does not need to ask for them — they are on by default.

Optional scopes are only included when the authorization request explicitly asks for them via the scope request parameter. If the client does not request an optional scope, its claims do not appear in the token. This keeps tokens small and avoids leaking unnecessary information.

Keycloak ships with a set of built-in client scopes that cover the most common needs:

ScopeClaims added
openidRequired for OIDC. Signals that the response is an ID token.
profilename, given_name, family_name, preferred_username
emailemail, email_verified
rolesrealm_access, resource_access
addressaddress (structured postal address)
phonephone_number, phone_number_verified
offline_accessGrants a refresh token that persists beyond the normal SSO session.
microprofile-jwtAdds claims for MicroProfile JWT compatibility.
  1. In the admin console, navigate to Clients and select your client.
  2. Click the Client scopes tab.
  3. You will see two sections: Assigned client scopes and Setup. The table shows scopes with their type (Default or Optional).
  4. To add a scope, click Add client scope (top-right of the assigned list).
  5. Select the scope name from the list, choose Default or Optional, and click Add.
  6. To request an optional scope at login time, include it in the scope parameter of the authorization request: scope=openid profile email address
  1. In the left sidebar, click Client scopes.
  2. Click Create client scope (top-right).
  3. Enter a Name (e.g., orders:read) and set Type to Optional.
  4. Click Save. You will land on the scope’s detail page with tabs: Settings, Mappers, Scope, Evaluate.
  5. Add mappers in the Mappers tab (see the Protocol Mappers lesson).
  6. Assign the scope to your client as described above.

Authorization request with scope parameter

Section titled “Authorization request with scope parameter”

When requesting an optional scope, include it in the scope query parameter of the authorization request:

https://auth.example.com/realms/my-app/protocol/openid-connect/auth?client_id=my-app-frontend&response_type=code&redirect_uri=https://app.example.com/callback&scope=openid%20profile%20email%20address

The %20 characters are URL-encoded spaces. Each scope name is space-separated (or %20-separated in the URL). Keycloak will only include the claims for the scopes listed here — and only if those scopes are assigned to the client (default or optional).

OptionBenefitCost
Default scopeEvery client automatically gets the same set of claims with no extra setup, reducing the chance of a missed assignmentThe token is always bigger, even for a client that never uses that claim
Optional scopeA smaller token, because it only carries the claims a client actually requested via the scope parameterThe client must remember to request the scope on every authorization request, or it won’t get the claim it needs
Split scopes per API (e.g. orders:read, billing:write) instead of one combined scopeFine-grained, least-privilege control per client and per use caseMore scopes and mappers to maintain, adding overhead
  • Making every custom scope a default scope — this bloats the token with claims most clients never use. Make it optional and let the clients that actually need it request it.
  • Forgetting to request a scope in the authorization request and then wondering why the claim is missing — assigning an optional scope to a client alone doesn’t make the claim appear in the token; it must also be listed in the request’s scope parameter.
  • Using one scope for several APIs with different permission levels — this gives every client that has the scope the same level of access. Split scopes according to each API’s risk level.

Real-world example

A multi-tenant SaaS platform — splits optional scopes by module, such as billing, reports, and admin, so each integration or third-party app’s token carries only the claims it needs for the module it requested.

An enterprise-grade API gateway — uses a default roles scope so every client always gets basic realm/client role claims, while a more sensitive scope such as financial data stays optional and is only granted to approved clients.

What is a client scope?
How do you request an optional client scope at authorization time?
Which built-in scope adds realm_access and resource_access to the token?
What is the difference between a Default scope and an Optional scope?