Protocol Mappers
What is a protocol mapper?
Section titled “What is a protocol mapper?”A protocol mapper transforms a piece of information — a user attribute, a group name, a hardcoded value — into a claim in the access token, ID token, or userinfo response. Without mappers, tokens only contain the basic OIDC claims Keycloak adds by default. Mappers are how you put custom, application-specific data into your tokens.
Mappers live inside client scopes (or directly on a client). When a scope is included in a token, all of its mappers run and their claims are added to the token.
Mapper types
Section titled “Mapper types”User Attribute mapper
Section titled “User Attribute mapper”Maps a custom user attribute (stored in the user’s profile under Attributes) to a claim. For example, if users have a department attribute set to "engineering", this mapper adds "department": "engineering" to the token.
Group Membership mapper
Section titled “Group Membership mapper”Adds a list of the user’s group memberships as a claim. Useful for coarse-grained authorisation based on groups rather than roles.
Hardcoded Claim mapper
Section titled “Hardcoded Claim mapper”Adds a fixed, static value to all tokens regardless of who the user is. For example, "api-version": "v2". Useful for versioning or flagging tokens for a specific environment.
Audience mapper
Section titled “Audience mapper”Adds a value to the aud claim so your API can verify it is the intended recipient. Without this, tokens may be accepted by unintended services. Every API that validates tokens should have an audience mapper so it can reject tokens not intended for it.
User Property mapper
Section titled “User Property mapper”Maps built-in user properties — email, username, firstName, lastName — to token claims. These are properties stored directly on the Keycloak user object (not custom attributes).
Role mapper (built-in via roles scope)
Section titled “Role mapper (built-in via roles scope)”The built-in roles scope ships with mappers that add realm_access and resource_access to the token. These contain the user’s realm-level and client-level roles respectively.
Adding a mapper to a client scope
Section titled “Adding a mapper to a client scope”- In the admin console, click Client scopes in the left sidebar.
- Click the name of the scope you want to add a mapper to.
- Click the Mappers tab.
- Click Add mapper → By configuration.
- Select the mapper type (e.g., User Attribute).
- Fill in:
- Name — a label for the mapper (e.g.,
department-claim). - User Attribute — the attribute name on the user object (e.g.,
department). - Token Claim Name — the key that will appear in the token (e.g.,
department). - Claim JSON Type — the value type: String, boolean, int, long, JSON.
- Add to ID token / Add to access token / Add to userinfo — toggle which tokens include this claim.
- Name — a label for the mapper (e.g.,
- Click Save.
Adding an Audience mapper
Section titled “Adding an Audience mapper”The Audience mapper is especially important for APIs. It ensures your API can verify the token was intended for it.
- In Client scopes, open your scope and click Mappers → Add mapper → By configuration.
- Select Audience.
- Enter the Name (e.g.,
orders-api-audience). - In Included Client Audience, select the client that represents your API (e.g.,
orders-api). - Enable Add to access token.
- Click Save.
- Now tokens issued for this scope will include
"aud": ["account", "orders-api"](or similar).
Token fragment after audience mapper
Section titled “Token fragment after audience mapper”After adding an Audience mapper and a User Attribute mapper for department, the access token payload will contain:
{
"aud": ["account", "orders-api"],
"azp": "my-app-frontend",
"scope": "openid profile email",
"department": "engineering"
}Trade-offs
Section titled “Trade-offs”| Option | Benefit | Cost |
|---|---|---|
| A “fat” token (many mappers and claims) | The backend can read claims straight from a single token, with no extra API call for user data | The token is bigger, affecting header size, and there’s more data at risk if the token leaks |
| A “thin” token (only the claims that are truly needed) | Smaller and safer, since less data is exposed if it leaks, and mappers are easier to maintain | The backend may need an extra query to get data that isn’t embedded in the token |
| Hardcoded claim mapper | Predictable value, good for debugging and for a fixed setting such as an audience | Inflexible — cannot vary per user, and must be edited whenever the value needs to change |
Common mistakes
Section titled “Common mistakes”- Putting mutable or frequently changing data in a claim (e.g. current role, account balance, subscription status) — a claim is a snapshot taken when the token was issued, not live data. If the real value changes, an old token keeps showing the stale value until it’s refreshed.
- Adding a mapper for every user attribute “just in case” — this bloats the token unnecessarily. Add mappers only for claims that have a real consumer.
- Forgetting to enable “Add to access token,” or enabling it in the wrong place (e.g. only for userinfo) — the mapper exists but the claim never appears in the actual access token, wasting debugging time.
Real-world example
An e-commerce platform — uses a group-membership mapper to put a customer’s tier (gold/silver) into the token so the frontend can adjust the UI immediately, while keeping the access-token lifespan short so an old tier doesn’t linger too long after an upgrade or downgrade.
Enterprise internal tools — choose a thin token with just
suband a basic role, then have the backend call a separate profile service when it needs more, to make sure the data shown is always current rather than a snapshot from login time.