WW-5727 fix(rest): authorize the @JsonIdentityInfo id property - #1943
Merged
Merged
Conversation
On a type whose @JsonIdentityInfo uses a property-based generator, BeanDeserializerFactory builds the ObjectIdReader before the deserializer modifiers run and captures the id property as it was then. ParameterAuthorizingModule then wraps every property in the builder, but the ObjectIdValueProperty Jackson adds at build time assigns the id through the reader's captured property, so the wrapper is never consulted and the id binds without a check. After wrapping, the module now rebuilds the reader with ObjectIdReader.construct around a wrapped id property, keeping the id type, property name, generator, deserializer and resolver. The id is then assigned through the wrapper's setAndReturn and authorized like any other property. Sequence-style generators carry no id property and are left alone. The wrapper's set and setAndReturn are no-ops over a creator property. Jackson skips the post-construction write of a creator-bound id itself by an instanceof CreatorProperty check the wrapper hides, and a record has no setter to write through, so wrapping the id plainly broke every record with a property-based id - through the builder's reader and through the one createContextual builds for a @JsonIdentityInfo placed on the referencing property. Leaving the reader alone for creator ids was not an option either: a repeated id key after construction wrote the creator property's fallback field unchecked. That repeated key is now dropped where stock Jackson would push it through the fallback field; the creator parameter is authorized through its own value deserializer. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
lukaszlenart
marked this pull request as ready for review
September 15, 2026 05:57
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.



Fixes WW-5727
Problem
On a type whose
@JsonIdentityInfouses a property-based generator,BeanDeserializerFactory.addObjectIdReaderruns before the deserializer modifiers and captures the idSettableBeanPropertyinto theObjectIdReader.ParameterAuthorizingModule.updateBuilderthen wraps every property in the builder, but theObjectIdValuePropertyJackson adds at build time assigns the id through the reader's captured property — the unwrapped one — so the id binds without a@StrutsParametercheck. Withidrejected,{"id":7,"name":"alice"}still setidto 7.Sibling of WW-5725 and WW-5726: a Jackson path that takes hold of the property before the modifier can wrap it.
Change
ObjectIdReader.construct(...)around a wrapper ofreader.idProperty, keeping the id type, property name, generator, deserializer and resolver. The id is then assigned through the wrapper'ssetAndReturnand authorized like any other property. Sequence-style generators carry no id property and are left alone.AuthorizingSettableBeanProperty.set/setAndReturnare no-ops over aCreatorProperty. Jackson skips the post-construction write of a creator-bound id itself by aninstanceof CreatorPropertycheck the wrapper hides (databind#5328), and a record has no setter to write through — wrapping the id plainly broke every record with a property-based id, both through the builder's reader and through the onecreateContextualbuilds for a@JsonIdentityInfoplaced on the referencing property. Leaving the reader alone for creator ids was not an option: a repeated id key after construction wrote the creator property's fallback field unchecked.Behaviour note
A key for a creator-bound property repeated after construction is now dropped, where stock Jackson pushes it through the creator property's fallback field (or throws for a record). The wrapper cannot tell that write from the one Jackson skips itself, so the creator's value stands. This applies whether or not authorization is active; it only affects bodies that repeat the key.
Tests
ParameterAuthorizingModuleTest: id rejected / granted on a plain bean; record with a property-based id — no context, authorized, rejected; per-property@JsonIdentityInfoon a record-typed member — no context and rejected; repeated id key after construction keeps the creator's value.mvn test -DskipAssembly -pl plugins/rest: 192 tests, 0 failures.🤖 Generated with Claude Code