fix: LazyInitializationException in PAT authentication on non-OSIV endpoints [DHIS2-21786]#24417
Open
netroms wants to merge 3 commits into
Open
fix: LazyInitializationException in PAT authentication on non-OSIV endpoints [DHIS2-21786]#24417netroms wants to merge 3 commits into
netroms wants to merge 3 commits into
Conversation
This was referenced Jul 10, 2026
Open
|
vietnguyen
approved these changes
Jul 10, 2026
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.



Jira: https://dhis2.atlassian.net/browse/DHIS2-21786
Same-repo rehost of #24407 so CI (including SonarQube) runs with repository secrets. Original work by @torbjorn from fork
torbjorn/dhis2-core.Problem
Authenticating with a personal access token on an endpoint excluded from open-session-in-view (e.g.
/api/dataValueSets, excluded since #23127) intermittently fails with HTTP 500:It happens when the token is not in the
apiTokenCache(first use, TTL expiry, or eviction), which makes it intermittent in production: whichever request happens to re-authenticate on a non-OSIV endpoint gets the 500. Reproduced against current master: the first request with a fresh PAT against/api/dataValueSetsreturns 500 with the exception above. Affects 2.43.0+ and master.ApiTokenAuthManager.validateAndCreateUserDetailslooks up the token owner viauserStore.getUserByUsernameand buildsUserDetailswith no transactional boundary. On non-OSIV endpoints the store returns a detached entity, andUserDetails.createUserDetailswalkinguser.getAuthorities()/user.getUserRoles()throws.Fix
Same pattern as #23611 (the JWT bearer equivalent of this bug): create the
UserDetailsviaUserService.createUserDetailsByUsername, which is@Transactional(readOnly = true), so lookup and lazy-collection access share one session. The PAT-specific validation (2FA/disabled/locked/expired) now reads the flags off the returnedUserDetails;DefaultUserService.createUserDetailscomputes the same flags the manager previously computed itself, and loads the same org-unit UID sets, so behavior is unchanged. The now-unusedUserStoreandOrganisationUnitServicedependencies are removed.Related: #23271 ("avoid lazy init on PAT first boot") sidestepped this for
/api/system/pingby making it unauthenticated; this PR fixes the underlying PAT path.Regression test
ApiTokenAuthTest(e2e, modeled on the JWT regression test inOAuth2Testfrom #23172): creates a user and a PAT, then issues the first request with that token (cold cache) against/api/dataValueSets. Verified againstdhis2/core-devimages: fails with the 500 above on unfixed master, passes with this fix (409 from the endpoint's parameter validation, i.e. authentication succeeded). Note: needs the e2e compose setup with an empty database (dhis-2/dhis-test-e2e/docker-compose.yml) — the helpers assume the bootstrap-seededSuperuserrole.Notes
Test plan
ApiTokenAuthTestpasses/api/dataValueSets) with cold token cache