Why Your Custom Keycloak Attribute Isn’t in the Token

Guilliano Molaire Guilliano Molaire 9 min read

Last updated: July 2026

A custom attribute only lands in a token if two things are true: (1) a protocol mapper of type “User Attribute” maps it into the access token, ID token, or userinfo endpoint, and (2) since Keycloak 24’s default-on declarative User Profile, the attribute must be explicitly declared in the realm’s User Profile schema — otherwise unmanaged attribute values may be silently ignored or not persisted at all. Add the mapper, declare the attribute, then confirm both are working with the client’s Client Scopes Evaluate tab.


The two layers most people miss

Keycloak enforces two separate checks before any attribute value reaches a token. Missing either one produces the same symptom: the claim is absent.

Layer 1 — User Profile declaration. Since Keycloak 24, the declarative User Profile is on by default. Keycloak now maintains a schema for the user record. An attribute not in that schema is “unmanaged,” and depending on the realm’s “Unmanaged Attributes” policy its value may be rejected or silently ignored. Keycloak will not surface undeclared attributes to mappers, even if a value was written before the v24 upgrade.

Layer 2 — Protocol mapper. Even after an attribute is declared and stored, Keycloak does not include it in any token automatically. A protocol mapper of type “User Attribute” must map the stored attribute name to a claim name, specify which token type receives it, and be attached to the client or a client scope the client uses.

Both layers wrong is the most common scenario for developers upgrading from pre-v24 or working on a fresh v24+ realm without knowing about the User Profile requirement.


Understanding declarative User Profile

Before Keycloak 24, user attributes were a free-form key-value store on the user record. You could write any attribute name to the Attributes tab and it would be saved. The only thing standing between storage and a token was a protocol mapper.

Starting with Keycloak 24, the Admin UI’s Realm Settings > User Profile page contains an authoritative list of allowed attribute names. The realm’s “Unmanaged Attributes Policy” controls what happens to attribute names not in that list:

Policy Behavior
Disabled (default in v24+) Unmanaged attributes are not allowed; writes are rejected
Enabled Unmanaged attributes can be read and written by admins only
Admin and self-managed Unmanaged attributes are available to users and admins

The “Disabled” default is the most common source of confusion. If you upgraded from v23 or earlier, your users may already have attribute values in the database, but those values will not flow through mappers until you either declare the attribute in User Profile or switch the policy.

How to declare an attribute in User Profile

  1. Open the Keycloak Admin Console and select your realm.
  2. Go to Realm Settings > User Profile.
  3. Click Create attribute.
  4. Set the Name to exactly the attribute key you use in the Attributes tab (e.g., department). The name is case-sensitive.
  5. Configure display name, validators, and permissions as needed. At minimum, set “Permissions — Who can edit?” to “Admin” if users should not self-edit this attribute.
  6. Click Save.

Once declared, new writes to that attribute name will be accepted and persisted, and existing values stored under that key will be surfaced to mappers.


Adding a User Attribute protocol mapper

With the attribute declared and stored, the next step is telling Keycloak to include it in tokens. You can do this per-client or on a shared client scope. The right choice depends on whether the claim should appear for every client or only specific ones.

Adding the mapper directly on a client

  1. Go to Clients > {your-client} > Client scopes.
  2. Click the dedicated scope link (it appears as {client-id}-dedicated).
  3. Click Add mapper > By configuration.
  4. Choose User Attribute.
  5. Fill in the fields:
    • Name: A label for this mapper (e.g., department-claim).
    • User Attribute: The exact attribute key from User Profile (e.g., department).
    • Token Claim Name: The claim name that will appear in the token (e.g., department, or a nested path like custom.department).
    • Claim JSON Type: String for most attributes; use JSON only for structured data.
    • Add to ID token: Enable if your application reads claims from the ID token.
    • Add to access token: Enable if APIs validate claims from the access token.
    • Add to userinfo: Enable if you fetch claims from the userinfo endpoint.
    • Multivalued: Enable if the attribute holds multiple values separated by ##.
    • Aggregate attribute values: Enable alongside Multivalued to merge values from multiple group memberships.
  6. Click Save.

This mapper is now attached only to this client’s dedicated scope. Every token issued to this client will include the department claim.

Adding the mapper to a shared client scope

For a claim that should appear across multiple clients, add the mapper to a shared client scope: go to Client Scopes > {your-scope} > Mappers > Add mapper > By configuration > User Attribute, configure the same fields, then assign the scope to each client under Clients > {client} > Client scopes > Add client scope. One mapper, updated in one place, benefits every client that includes the scope.


The “only appears after profile update” symptom

If the claim appears after a user saves their profile but not on initial login, this is a User Profile persistence issue. An administrator wrote the attribute value before the attribute was declared in the schema. Admin-level writes can bypass User Profile validation, so the value exists in the database but is not surfaced to mappers at login time.

When the user saves their profile through the account console, the write goes through the User Profile layer with the attribute now declared, and subsequent logins include the claim.

The fix: Declare the attribute in Realm Settings > User Profile, then re-write the value for all affected users via the Admin REST API (PUT /admin/realms/{realm}/users/{id}). There is no need to re-create users — just PATCH the attributes field.

For how attributes flow across brokering scenarios, see attribute mapping in Keycloak during OIDC identity brokering.


Verifying with the Evaluate tab

Before testing in your application, confirm the mapper is working using the built-in Evaluate tab. This saves a round-trip through your application stack.

  1. Go to Clients > {your-client} > Client scopes.
  2. Click the Evaluate tab.
  3. In the User field, select a user you know has the attribute set.
  4. Click Evaluate.
  5. Under Generated access token, look for your claim name. If it is present with the correct value, the mapper and User Profile declaration are correct.
  6. If the claim is absent, expand the Effective protocol mappers list below to confirm your mapper appears. If it does not appear, the scope it belongs to is not assigned to this client.

The Evaluate tab is also the fastest way to check the JWT token lifecycle — you can see exactly which claims are present at issuance without decoding a live token. If you need to inspect a real token from your application, paste it into the Skycloak JWT Token Analyzer to decode and verify claims interactively.


Checklist: symptom, cause, and fix

Symptom Most likely cause Fix
Claim absent for every user No protocol mapper exists Add a User Attribute mapper to the client’s dedicated scope or a shared scope
Claim absent for every user Mapper on a scope not assigned to this client Go to Clients > {client} > Client scopes and add the scope
Claim absent for every user Wrong token target selected on mapper Review “Add to access token” / “Add to ID token” checkboxes
Claim absent for every user Attribute not declared in User Profile Declare under Realm Settings > User Profile
Claim absent for some users Attribute value not set for those users Check Admin Console > Users > {user} > Attributes
Claim absent for some users Stale sessions from before mapper was added Revoke sessions; users log out and back in
Claim absent for some users Attribute written before User Profile declaration Re-write attribute via Admin REST API after declaring it
Claim appears only after profile update Value written by admin before attribute was declared Declare attribute; re-write value for affected users via REST API
Claim name wrong in token “User Attribute” and “Token Claim Name” confused Re-check both mapper fields; use dot-notation for nested claims
Multivalued attribute is a single string “Multivalued” is off Enable “Multivalued” on mapper; store values separated by ##

For API-side validation of the resulting claims, see Keycloak token validation for APIs.


Common mistakes at a glance

Wrong token target. The mapper has “Add to access token” enabled but your application reads the ID token — or the reverse. Check which token your application actually inspects before debugging further.

Claim name mismatch. “User Attribute” (the stored key) and “Token Claim Name” (the JWT output key) are two separate fields and do not have to be identical. A mismatch between them is a frequent source of “claim missing” reports. Both are case-sensitive.

Mapper not in scope. A mapper on a client scope that is not assigned to the client will never fire. Verify the scope is listed under the client’s Client Scopes tab as “Default” or “Optional.” For optional scopes, confirm the client actually requests the scope in the authorization request.

Duplicate mappers. Adding the same mapper to both a shared client scope and the client’s dedicated scope results in duplicate claims in the token. Pick one location.

Stale token. After adding a new mapper, existing sessions use the old token until it expires or is refreshed. Review your JWT token expiration strategy if stale claims are a recurring issue.


Keycloak 26.x-specific notes

As of Keycloak 26, the declarative User Profile is the only supported model. The legacy “User Profile Provider” toggle from earlier 24/25 releases has been removed. Every realm operates under the schema-based User Profile, and the “Unmanaged Attributes” policy is the only way to accommodate attribute values that predate the schema.

Keycloak 26 also groups mapper types in the “By configuration” dialog (Token mappers, Role mappers, Hardcoded mappers, etc.), making the User Attribute mapper easier to locate. The Admin REST API (GET /admin/realms/{realm}/users/{id}) now separates declared and unmanaged attribute values in the response when the Unmanaged Attributes policy permits them — scripts that relied on the flat attributes map should be updated accordingly.

For teams managing attributes programmatically across a large user base, see the using custom user attributes in Keycloak OIDC tokens guide, which covers scripted attribute provisioning patterns.


Frequently asked questions

Why is my custom attribute not in the Keycloak token?

Two things must both be true. First, the attribute must be declared in the realm’s User Profile schema under Realm Settings > User Profile — a requirement added by default in Keycloak 24. Second, a protocol mapper of type “User Attribute” must exist on the client or on a client scope assigned to the client, with the correct attribute key, claim name, and token target. If either is missing, the claim is absent.

What is declarative User Profile in Keycloak?

It is a schema that defines which attribute names are valid on the user record. Each attribute must be declared with its name, validators, and access permissions under Realm Settings > User Profile. Since Keycloak 24 this is on by default, and the “Unmanaged Attributes” policy controls what happens to names outside the schema. Full details are in the Keycloak Server Administration Guide.

How do I add a custom claim to a Keycloak token?

Go to Clients > {your-client} > Client scopes > {client-id}-dedicated > Add mapper > By configuration > User Attribute. Set “User Attribute” to the stored key, set “Token Claim Name” to the desired claim name in the JWT, enable the appropriate token targets, and save. Confirm the claim appears using the Evaluate tab before testing in your application.

Why does my attribute only appear in the token after the user updates their profile?

The attribute value was written to the user record before the attribute was declared in User Profile. Admin writes can bypass the schema check, so the value exists in the database but is not surfaced by mappers. When the user saves their profile, the write goes through the schema and persists correctly. Fix: declare the attribute, then re-write the value for affected users via the Admin REST API (PUT /admin/realms/{realm}/users/{id}).

Can I add a custom attribute to tokens for all clients at once?

Yes. Add the mapper to a shared client scope under the top-level Client Scopes menu, then assign that scope to each client under Clients > {client} > Client scopes. Every client that includes the scope receives the claim. This is the preferred approach for organization-wide attributes like department or tenant_id. See client scopes in Keycloak for guidance on when shared scopes are the right choice.


Conclusion

Custom attributes missing from tokens almost always trace back to two missed steps: declaring the attribute in User Profile and adding a User Attribute protocol mapper. The sequence every time: declare the attribute under Realm Settings > User Profile, confirm the value is stored on the user record, add the mapper to the client’s dedicated scope or a shared scope, then verify with the Evaluate tab. The checklist above covers the remaining edge cases — wrong token target, stale sessions, multivalued configuration.

If managing Keycloak configuration across development, staging, and production is a recurring burden, Skycloak handles the infrastructure and upgrades so your team can focus on building. See Skycloak’s managed Keycloak plans.

Tired of running Keycloak yourself?

Skycloak runs real upstream Keycloak for you with a 99.99% SLA. No fork, no lock-in, just managed Keycloak that stays patched and on call so you don't have to.

Guilliano Molaire
Written by
Founder

Guilliano is the founder of Skycloak and a cloud infrastructure specialist with deep expertise in product development and scaling SaaS products. He discovered Keycloak while consulting on enterprise IAM and built Skycloak to make managed Keycloak accessible to teams of every size.

Start Free Trial Talk to Sales
© 2026 Skycloak. All Rights Reserved. Design by Yasser Soliman