KNOX-3403: RFC 8693 token exchange: use the impersonated subject as the token sub on non-server-managed topologies - #1336
Merged
Conversation
…he token sub on non-server-managed topologies
Test Results40 tests 40 ✅ 6s ⏱️ Results for commit eb26d71. |
smolnar82
added a commit
that referenced
this pull request
Jul 31, 2026
…he token sub on non-server-managed topologies (#1336)
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.
KNOX-3403 - Token exchange issues the wrong
subon non-server-managed topologiesWhat changes were proposed in this pull request?
When a token was issued under impersonation via an RFC 8693 token exchange (
subject_token+actor_token) on a topology that is not server-managed, the issued JWT'ssubwas set to the actor (the primary principal / authenticated caller) instead of the subject (the impersonated end user) - so the token represented the acting party rather than the user, defeating the on-behalf-of semantics. (Theactclaim was already correct; onlysubwas wrong.)Root cause:
TokenResource.buildUserContext(...)only replaced the default username (the primary principal, fromrequest.getUserPrincipal()) with the impersonated principal inside anif (tokenStateService != null)block - i.e. only when the topology is server-managed. That gate predates token exchange and was intended only to guard metadata storage (userName/createdBypersisted to the token state service), not to control the issued token'ssub.This PR moves the impersonation ->
userNameresolution out of that gate, so the issued token'ssubis the effective (impersonated) identity wheneverSubjectUtils.isImpersonating(subject)is true, independent of server-managed state.createdBycontinues to be persisted only for managed tokens (persistTokenDetailsalready guards ontokenStateService != null, so computing it otherwise is harmless). The stale comment was updated.Scope: only the non-server-managed impersonation path changes. Traditional
doAswas already correct (the identity-assertion request wrapper exposes the impersonated user viagetUserPrincipal()), server-managed topologies are unchanged, and non-impersonating requests are unchanged.How was this patch tested?
sub = <actor>(wrong); the same exchange on a server-managed topology returned the correctsub, isolating the cause to this gate.TokenServiceResourceTest:testImpersonatedTokenSubjectOnNonServerManagedTopology: non-server-managed + impersonation (actoradmin, subjectbob) assertssub == bobandact == { sub: admin }.testNonImpersonatedTokenSubjectOnNonServerManagedTopology: non-server-managed, no impersonation assertssub == <primary>and noactclaim (no regression).expected:<bob> but was:<alice>) and pass with it; fullTokenServiceResourceTestpasses (73 tests) with 0 Checkstyle violations.Manual testing:
Step 1 - mint two DISTINCT Knox tokens from sandbox (subject ≠ actor, so act populates)
Step 2 - create a NON‑server‑managed exchange topology obo
All tokens here are Knox‑issued (iss=KNOXSSO, typ=JWT), so no JWKS/CA/typ‑ignore needed — Knox verifies them with its own key;
conf/topologies/obo.xmllooks like this:Notes:
enable.delegated.authadds theactclaim.)Step 3 - verification
Verified these combinations:
oboenable.delegated.auth=true)sub=tom,act={sub:sam}enable.delegated.auth=falsesub=tom, noactactgated on delegated auth$SUBJ)sub=tom, noactknox.token.exp.server-managed=trueon the KNOXTOKEN servicesub=tom,act={sub:sam}tokenStateService != null, so the correct subject is used (works even without the fix)knox.token.exp.server-managed=trueon the JWTProvider401 "Unknown token"I used the following
curlcommand and its variations:Step 4 -
doAssanity check onsandbox(should be unchanged by this PR to confirm no regression):Integration Tests
N/A
UI changes
N/A