Pass through unrecognized claims in check_token and introspect responses - #4065
Pass through unrecognized claims in check_token and introspect responses#4065duanemay wants to merge 2 commits into
Conversation
There was a problem hiding this comment.
🟡 Changes recommended
IntrospectionClaims#getAdditionalClaims() exposes a mutable backing map, which can lead to unintended external mutation of serialized/introspection output.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Pull request overview
This PR updates the token introspection claim model so /introspect responses can include JWT extension (previously-unmapped) top-level claims, instead of silently dropping them during deserialization.
Changes:
- Capture unknown JSON/JWT claim members in
IntrospectionClaimsvia@JsonAnySetterand serialize them back out via@JsonAnyGetter. - Add a unit test to verify an unmapped claim survives deserialize → serialize and appears at the top level of the JSON output.
File summaries
| File | Description |
|---|---|
| model/src/main/java/org/cloudfoundry/identity/uaa/oauth/token/IntrospectionClaims.java | Adds an “additional claims” map and Jackson any-setter/any-getter flattening to preserve extension members. |
| model/src/test/java/org/cloudfoundry/identity/uaa/oauth/token/IntrospectionClaimsTest.java | Adds coverage to confirm unknown claims round-trip and reappear in serialized JSON. |
Review details
- Files reviewed: 2/2 changed files
- Comments generated: 1
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
CheckTokenEndpoint and IntrospectEndpoint both decode a JWT into a Claims/IntrospectionClaims POJO with @JsonIgnoreProperties(ignoreUnknown = true), so any top-level claim without a matching field is silently dropped from the response. Capture unrecognized claims on the shared Claims class via @JsonAnySetter/@JsonAnyGetter and re-flatten them back to top level on serialization, so both endpoints now return the full set of claims present in the token instead of only the curated subset.
a2772ea to
8a23093
Compare
There was a problem hiding this comment.
🟡 Changes recommended
The newly added tests include assertions that are currently too weak to reliably validate the intended “flattened at top level” behavior and correct value round-tripping.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Review details
- Files reviewed: 3/3 changed files
- Comments generated: 2
- Review effort level: Lite
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
9c0455a to
ced0dab
Compare
Summary
CheckTokenEndpointandIntrospectEndpointboth decode a JWT into aClaims/IntrospectionClaimsPOJO annotated@JsonIgnoreProperties(ignoreUnknown = true), so any top-level claim without a matching field is silently dropped from the response.Claimscaptures unrecognized claims via@JsonAnySetterand re-flattens them back to top level on serialization via@JsonAnyGetter, instead of discarding them.members beyond the standard set, and clients "SHOULD" ignore unrecognized ones.
Claimsclass, this change applies to both/check_tokenand/introspect— any claim added to a token (e.g. by a customUaaTokenEnhancer) that isn't one of the explicitly modeled fields now shows up in both endpoints' responses.Test plan
IntrospectionClaimsTest— verifies an unrecognized claim round-trips through deserialize/serialize and appears at the top level of the JSON output.CheckTokenEndpointTests#additionalClaimsInResult— verifies custom top-level claims added by aUaaTokenEnhancer(ex_groups,ex_prop) are no longer dropped from the/check_tokenresponse.IntrospectionClaimsTest,IntrospectEndpointTest, andCheckTokenEndpointTestssuites pass unchanged.