fix: correctly handle duplicate values in setAttribute()#48384
fix: correctly handle duplicate values in setAttribute()#48384ahus1 merged 2 commits intokeycloak:mainfrom
Conversation
20bfcb0 to
505b353
Compare
Unreported flaky test detectedIf the flaky tests below are affected by the changes, please review and update the changes accordingly. Otherwise, a maintainer should report the flaky tests prior to merging the PR. org.keycloak.testsuite.forms.MultiFactorAuthenticationTest#testAlternativeMechanismsInDifferentSubflowsKeycloak CI - Forms IT (chrome) |
|
I see there's #41432, which you have contributed to, but it appears to be abandoned. Let's proceed here and we can close that PR once this has been merged. |
|
Yes, #41432 is much more complex and does also not work. So I started a completely new approach. And it turns out that it is quite easy to fix. |
) When an attribute holds duplicate values (e.g. ["bar", "bar"]) and the caller reduces the count (e.g. to ["bar"]), the change was silently dropped. Both the infinispan cache adapter and the JPA adapter compared old and new values as Sets, so ["bar", "bar"] and ["bar"] both collapsed to {"bar"} and the equality check returned true, causing an early return without persisting any change. The infinispan adapter's check is the primary failure point in real deployments: it guards the call to getDelegateForUpdate(), so the JPA layer was never reached at all. Fix: replace Set-based comparison with List-based comparison in both adapters. CollectionUtil.collectionEquals already counts duplicates correctly when given Lists, so ["bar", "bar"] vs. ["bar"] correctly evaluates to not-equal and the update proceeds. Includes a regression test that verifies duplicate-value reduction is persisted correctly across transaction boundaries. closes keycloak#38526 Signed-off-by: Niko Köbler <[email protected]>
505b353 to
c8545a8
Compare
Unreported flaky test detectedIf the flaky tests below are affected by the changes, please review and update the changes accordingly. Otherwise, a maintainer should report the flaky tests prior to merging the PR. org.keycloak.testsuite.adapter.servlet.SAMLServletAdapterTest#employeeSigPostNoIdpKeyTestCertSubjectAsKeyNameInKeyInfoKeycloak CI - Adapter IT Strict Cookies |
ryanemerson
left a comment
There was a problem hiding this comment.
LGTM, thanks @dasniko
Signed-off-by: Alexander Schwartz <[email protected]>
2721154 to
f937a0c
Compare
|
Thank you for this PR @dasniko and thank you for the first review @ryanemerson. I've reviewed it and found a similar log in the The database stores the value as a "bag", which is unordered. Unfortunately there is no native Java type for that, so I chose to sort the list and then compare. Please have a look. Once one of you has reviewed this change, I'll merge it and prepare the backports. |
ryanemerson
left a comment
There was a problem hiding this comment.
Thanks for the second pair of eyes @ahus1, good catch!
|
Thanks @ahus1! LGTM |
Unreported flaky test detectedIf the flaky tests below are affected by the changes, please review and update the changes accordingly. Otherwise, a maintainer should report the flaky tests prior to merging the PR. org.keycloak.testsuite.authz.PolicyEvaluationTest# |
|
Re-running the Store model tests as |
Unreported flaky test detectedIf the flaky tests below are affected by the changes, please review and update the changes accordingly. Otherwise, a maintainer should report the flaky tests prior to merging the PR. org.keycloak.testsuite.authz.PolicyEvaluationTest# |
When an user attribute holds duplicate values (e.g. ["bar", "bar"]) and the caller reduces the count (e.g. to ["bar"]), the change was silently dropped. Both the infinispan cache adapter and the JPA adapter compared old and new values as Sets, so ["bar", "bar"] and ["bar"] both collapsed to {"bar"} and the equality check returned true, causing an early return without persisting any change.
The infinispan adapter's check is the primary failure point in real deployments: it guards the call to getDelegateForUpdate(), so the JPA layer was never reached at all.
Fix: replace Set-based comparison with List-based comparison in both adapters. CollectionUtil.collectionEquals already counts duplicates correctly when given Lists, so ["bar", "bar"] vs. ["bar"] correctly evaluates to not-equal and the update proceeds.
Includes a regression test that verifies duplicate-value reduction is persisted correctly across transaction boundaries.
closes #38526
🤖 AI disclosure: The analysis of the issue and the proposed changes were done with the help of Claude Code. The implementations, especially the new test method, was done myself. Claude also wrote the commit message.