TOMEE-4648 - BASIC mechanism rejects valid credentials with an application IdentityStore - #2851
TOMEE-4648 - BASIC mechanism rejects valid credentials with an application IdentityStore#2851jungm wants to merge 2 commits into
Conversation
The BASIC mechanism passed a BasicAuthenticationCredential to IdentityStoreHandler.validate(Credential). The spec's default IdentityStore.validate(Credential) dispatches to a validate(...) overload only on an exact parameter-type match, and BasicAuthenticationCredential is a subclass of UsernamePasswordCredential, so an application store declaring the idiomatic validate(UsernamePasswordCredential) overload was never invoked and returned NOT_VALIDATED - producing a 401 for valid credentials. Built-in stores were unaffected, so it only surfaced with an application-supplied IdentityStore. Hand the identity store a plain UsernamePasswordCredential (reusing the already-parsed Password) while still parsing the header via BasicAuthenticationCredential. Adds a test mirroring the TCK app-mem-basic identity store.
|
Diagnosis is right and matches the RI — Soteria's Three things before merge:
Follow-up JIRA worth filing: |
… NOT_VALIDATED
Review follow-ups on the BASIC credential fix:
- Scope the test IdentityStore. beans.xml is a bare <beans/> and
AbstractTomEESecurityTest deploys the whole test-classes tree as one
webapp, so the store was an active authentication store for every test
in the module. It now answers only for the 'reza' caller - which exists
in no other test and in no tomcat-users.xml entry - and returns
NOT_VALIDATED_RESULT otherwise, so the handler falls through to the
remaining stores exactly as if it were not deployed.
- Assert the negative role case ('kaz': false), which the servlet already
writes but the test did not check.
- Log at debug in TomEEIdentityStoreHandler when no store validated the
credential. This exact-parameter-type dispatch failure was completely
silent - the caller just saw a 401 - which is what made TOMEE-4648 hard
to pin down.
|
Thanks — all three addressed in 6f0e1f9, plus the two follow-ups filed. 1. Behaviour change documented. Added a "Behaviour change (release note)" section to TOMEE-4648 spelling out that a store declaring Took the debug-logging suggestion in this PR rather than deferring it: 2. Test store scoped. You're right that a bare 3. Re-verified the test still fails without the production hunk ( Follow-up filed: TOMEE-4660 for the OpenID path — confirmed 🤖 Addressed by Claude Code |
rzo1
left a comment
There was a problem hiding this comment.
can you run a full build for this one on CI ?
|
Currently short on time, so AI review only: I ran an adversarial review pass over this PR, followed by a second pass whose job was to refute the first one's findings against the actual code. Everything below survived that second pass. Take it as input, not as a verdict — I have not run the build. Overall: the core fix is correct and well-diagnosed. Confirmed against the bytecode of The findings are all about the diagnostics half of the PR. 1. The new debug message is silent in exactly the case it was written for (minor)
This is not hypothetical for this PR's own reproducer: The log would need to sit before the 2. …and it fires on ordinary wrong-password logins, misdiagnosing them (minor)
Combined with finding 1: the message is silent where it is needed and misleading where it is not. If the block stays where it is, the wording should not assert an overload mismatch as the cause. 3. Stores declaring
|
What
Fixes TOMEE-4648: the BASIC authentication mechanism answered
401for valid credentials when validation went against an application-suppliedIdentityStore.Why
BasicAuthenticationMechanismpassed aBasicAuthenticationCredentialtoIdentityStoreHandler.validate(Credential). The spec's defaultIdentityStore.validate(Credential)dispatches to avalidate(...)overload only on an exact parameter-type match — its javadoc states explicitly that it does not look for the most specific overload. SinceBasicAuthenticationCredential extends UsernamePasswordCredential, a store declaring the idiomaticvalidate(UsernamePasswordCredential)overload (exactly what the Jakarta Security TCK'sTestIdentityStoredoes) was never invoked and returnedNOT_VALIDATED, producing a 401.Built-in stores (e.g. Tomcat users) declare their own credential handling and were unaffected, which is why this only surfaced with an application store — and why the plain, decorated, and custom-handler TCK variants all failed the same
testAuthenticatedcheck.Change
BasicAuthenticationMechanism.validateRequeststill parses theAuthorizationheader viaBasicAuthenticationCredential(which does the base64 decoding), but now hands the identity store a plainUsernamePasswordCredential, reusing the already-parsedPassword(no plaintext round-trip). The empty/malformed-header path is unchanged — the constructor still throwsIllegalArgumentException, caught as before to fall through to the challenge.Tests
Tomee4648BasicGroupsTestmirrors the TCKapp-mem-basicmodule (an@ApplicationScoped IdentityStorewith only thevalidate(UsernamePasswordCredential)overload). It fails with 401 before the change and passes after, asserting caller name and both groups.tomee-securitymodule is green (108 tests), including the existing BASIC negative cases (wrong password, unknown user, missing role).TCK impact
Removes the cause of these exclusions in the apache/tomee-tck
securityrunner:AppMemBasicIT#testAuthenticatedAppMemBasicDecorateIT#testAuthenticatedAppCustomAuthenticationMechanismHandler2ITNote for reviewers
The two OpenID TCK modules originally bundled into TOMEE-4648 were not a TomEE bug — they were a test-harness environment issue (the bundled OpenID provider's
startup.shneedsJAVA_HOME, which was unset). Both pass unchanged onceJAVA_HOMEis set; that fix lives in apache/tomee-tck and is out of scope for this PR. The ticket has been updated accordingly.🤖 Generated with Claude Code