8000 Map non-string claims in the IdP user session note mapper by baptistegh · Pull Request #55075 · keycloak/keycloak · GitHub
[go: up one dir, main page]

Skip to content

Map non-string claims in the IdP user session note mapper - #55075

Open
baptistegh wants to merge 2 commits into
keycloak:mainfrom
baptistegh:idp-session-note-mapper-non-string-claims
Open

baptistegh wants to merge 2 commits into
keycloak:mainfrom
baptistegh:idp-session-note-mapper-non-string-claims

Conversation

@baptistegh
@baptistegh baptistegh commented Nov 12, 2026 •
Copy link
Copy Markdown

Related to #45938

The OIDC "User Session Note" identity provider mapper currently ignores any claim that is not a string, so arrays, objects, numbers or booleans coming from an external IdP never make it into the user session.

I had a look at #45939 before opening this, since it targets the same issue. I ended up going a slightly different way on the IdP side, so I thought it would be easier to open a separate PR you can compare, rather than leave a long list of comments on someone else's work. Happy to close this one or help merge both approaches if that works better.

The idea was to behave the same way as the existing OID4VP SD-JWT user session attribute mapper (OID4VPSdJwtUserSessionAttributeMapper), which already handles this case: array elements are joined with a comma, objects are stored as their JSON representation and other values as their text. Like the OID4VP mapper, there is no new configuration option.

Main differences with #45939:

  • array elements are joined explicitly instead of using List.toString() and stripping spaces and brackets, so the content of each entry is kept as is (spaces, URLs, colons...)
  • no restriction on the characters allowed in array elements
  • when an array claim is compared to the configured value, each element is checked, so pwd matches ["pwd","mfa"] and the note is set to pwd,mfa
  • objects, numbers and booleans are supported too
  • an empty value stores the claim whatever it contains (see below)

The mapper only stores a claim when it matches a configured value, which does not work well for something like amr, where you usually want to forward whatever the IdP sent. So if the value is left empty, the claim is now stored as is, whatever its type and whether "Regex Claim Values" is enabled. This is also closer to the OID4VP mapper, which always stores the claim. An empty value could never match before, except for a claim that is literally an empty string, so existing configurations should not be affected.

For regular expressions I kept the current behavior on purpose: with "Regex Claim Values" enabled, only string claims are matched and other types are skipped with a warning, as today. Run 8000 ning a regex against the serialized form of an array or an object felt fragile and could easily match more than people expect. With the empty value option above, there is still a way to map arrays when you do not know their values in advance.

This PR does not change the token side. A mapped array ends up as the string pwd,mfa in the client token, not as a JSON array, while objects can be turned back into JSON with the JSON claim type. #45939 adds an Array JSON type in OIDCAttributeMapperHelper for this, but I think it deserves its own discussion since it applies to every OIDC protocol mapper exposing the claim JSON type. That is also why this PR only references the issue and does not close it.

The new tests are unit tests in ClaimToUserSessionNoteMapperTest, covering each claim type with and without regex, the empty value, and missing or empty claims. The existing integration test is unchanged, since string claims behave exactly as before.

@baptistegh
baptistegh marked this pull request as ready for review November 12, 2026 07:10
@baptistegh
baptistegh requested a review from a team as a code owner November 12, 2026 07:10
Copilot AI balanced review requested due to automatic review settings November 12, 2026 07:10
Copilot AI left a comment
Copy link
Copy Markdown
Contributor

Choose a reason f 8000 or hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Claim conversion drops non-text UserInfo array elements and null-valued token object properties, causing missing or incomplete session notes and incorrect configured-value matching.

2 open issues
What changed in this PR

Extends the OIDC identity-provider user session note mapper to support non-string claims, addressing the IdP-side portion of #45938 without changing token-side protocol mappers.

Changes:

  • Matches array elements individually and stores values as comma-separated text.
  • Adds JSON object and scalar conversion while retaining string-only regex matching.
  • Documents the behavior and adds unit tests for matching and serialization.
File Description
services/​src/​test/​java/​org/​keycloak/​broker/​oidc/​mappers/​ClaimToUserSessionNoteMapperTest.java Adds tests for supported claim types, regex matching, and missing or unmatched claims.
services/​src/​main/​java/​org/​keycloak/​broker/​oidc/​mappers/​ClaimToUserSessionNoteMapper.java Implements non-string claim conversion and array matching; updates mapper documentation.

Review effort: Balanced

@baptistegh
baptistegh force-pushed the idp-session-note-mapper-non-string-claims branch from 7655ce4 to a831a83 Compare November 12, 2026 07:18
Copilot AI balanced review requested due to automatic review settings November 12, 2026 07:18
Copilot AI left a comment
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

UserInfo claim arrays lose non-string elements, and token object claims lose null-valued members, causing incomplete session notes and failed JSON matches.

2 open issues

Review effort: Balanced

@baptistegh
baptistegh force-pushed the idp-session-note-mapper-non-string-claims branch from a831a83 to eb3e78a Compare November 12, 2026 07:23
Copilot AI balanced review requested due to automatic review settings November 12, 2026 07:23
Copilot AI left a comment
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

With keepArrays enabled, claim traversal can return an array before resolving the full path, allowing a note to be stored for a nonexistent claim.

2 open issues
1 resolved since last review

Review effort: Balanced

@baptistegh
baptistegh force-pushed the idp-session-note-mapper-non-string-claims branch from eb3e78a to 5039fd0 Compare November 12, 2026 08:39
Copilot AI balanced review requested due to automatic review settings November 12, 2026 08:39
Copilot AI left a comment
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

A missing field in a nested claim path can trigger an unchecked null dereference, aborting broker login instead of skipping the missing claim.

1 open issue
2 resolved since last review

Review effort: Balanced

Comment on lines +260 to +262
if (keepArrays) {
// keep walking the path, so that an array is only returned if it is the claim itself
continue;
The OIDC user session note IdP mapper skipped every claim that was not a
string, so arrays, objects, numbers and booleans could not be propagated to
the user session

Store them as the OID4VP SD-JWT user session attribute mapper does: array
elements are joined with a comma, objects are stored as their JSON
representation and scalars as their text. An array claim matches when any of
its elements equals the configured value

Arrays found in the UserInfo claim set are kept with all their elements, as
the shared lookup otherwise only returns their text elements, and null
properties of object claims are kept in their JSON representation

Regular expressions still only match string claims, so a pattern never
matches the serialized form of an array or object

An empty configured value stores the claim as is, whatever its type and
whether regular expressions are enabled, so a claim such as amr can be
propagated without knowing its values in advance. An empty value never
matched before, except for an empty string claim, so existing configurations
keep their behavior

Assisted-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Baptiste Gouhoury <gouhoury.baptiste@gmail.com>
@baptistegh
baptistegh force-pushed the idp-session-note-mapper-non-string-claims branch from 5039fd0 to d6115fa Compare November 12, 2026 08:49
Copilot AI balanced review requested due to automatic review settings November 12, 2026 08:49
Copilot AI left a comment
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

No active review issues were identified for the OIDC session-note mapper’s non-string claim support.

1 open issue

Review effort: Balanced

@baptistegh
Copy link
Copy Markdown
Author

Hi @sschu,
Can I have a review on this one? I don't know who is in charge of this area.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

0