Skip to content

Protocol Mappers

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.

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.

Adds a list of the user’s group memberships as a claim. Useful for coarse-grained authorisation based on groups rather than roles.

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.

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.

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).

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.

  1. In the admin console, click Client scopes in the left sidebar.
  2. Click the name of the scope you want to add a mapper to.
  3. Click the Mappers tab.
  4. Click Add mapper → By configuration.
  5. Select the mapper type (e.g., User Attribute).
  6. 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.
  7. Click Save.

The Audience mapper is especially important for APIs. It ensures your API can verify the token was intended for it.

  1. In Client scopes, open your scope and click Mappers → Add mapper → By configuration.
  2. Select Audience.
  3. Enter the Name (e.g., orders-api-audience).
  4. In Included Client Audience, select the client that represents your API (e.g., orders-api).
  5. Enable Add to access token.
  6. Click Save.
  7. Now tokens issued for this scope will include "aud": ["account", "orders-api"] (or similar).

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"
}
OptionBenefitCost
A “fat” token (many mappers and claims)The backend can read claims straight from a single token, with no extra API call for user dataThe 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 maintainThe backend may need an extra query to get data that isn’t embedded in the token
Hardcoded claim mapperPredictable value, good for debugging and for a fixed setting such as an audienceInflexible — cannot vary per user, and must be edited whenever the value needs to change
  • 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 sub and 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.

What does a protocol mapper do?
Why should you add an Audience mapper to your API client scope?
Which mapper type adds a fixed value to every token?
Where do you add a mapper in the admin console?