Skip to content

WW-5727 fix(rest): authorize the @JsonIdentityInfo id property - #1943

Merged
lukaszlenart merged 1 commit into
mainfrom
WW-5727
Sep 15, 2026
Merged

lukaszlenart merged 1 commit into
mainfrom
WW-5727

Conversation

@lukaszlenart

Copy link
Copy Markdown
Member

Fixes WW-5727

Problem

On a type whose @JsonIdentityInfo uses a property-based generator, BeanDeserializerFactory.addObjectIdReader runs before the deserializer modifiers and captures the id SettableBeanProperty into the ObjectIdReader. ParameterAuthorizingModule.updateBuilder then wraps every property in the builder, but the ObjectIdValueProperty Jackson adds at build time assigns the id through the reader's captured property — the unwrapped one — so the id binds without a @StrutsParameter check. With id rejected, {"id":7,"name":"alice"} still set id to 7.

Sibling of WW-5725 and WW-5726: a Jackson path that takes hold of the property before the modifier can wrap it.

Change

  • After wrapping, the module rebuilds the reader with ObjectIdReader.construct(...) around a wrapper of reader.idProperty, 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.
  • AuthorizingSettableBeanProperty.set/setAndReturn are no-ops over a CreatorProperty. Jackson skips the post-construction write of a creator-bound id itself by an instanceof CreatorProperty check 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 one createContextual builds for a @JsonIdentityInfo placed 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 @JsonIdentityInfo on 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

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
lukaszlenart marked this pull request as ready for review September 15, 2026 05:57
@sonarqubecloud

Copy link
Copy Markdown

@lukaszlenart
lukaszlenart merged commit 6b246ae into main Sep 15, 2026
13 checks passed
@lukaszlenart
lukaszlenart deleted the WW-5727 branch September 15, 2026 06:23
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.

1 participant