Skip to content

KNOX-3424: Complete RFC 8707/8693 dynamic resource/audience handling in KNOXTOKEN and token exchange - #1373

Merged
smolnar82 merged 5 commits into
apache:masterfrom
smolnar82:KNOX-3424
Sep 3, 2026
Merged

KNOX-3424: Complete RFC 8707/8693 dynamic resource/audience handling in KNOXTOKEN and token exchange#1373
smolnar82 merged 5 commits into
apache:masterfrom
smolnar82:KNOX-3424

Conversation

@smolnar82

Copy link
Copy Markdown
Contributor

KNOX-3424 - Complete RFC 8707/8693 dynamic resource/audience handling in KNOXTOKEN and token exchange

What changes were proposed in this pull request?

Follow-up to #1356, finishing the dynamic-audience work so Knox implements both RFC 8707 (Resource Indicators) and RFC 8693 (Token Exchange) end to end. Three self-contained commits:

  1. Replace the audience query param with a URL-validated resource param.
    The KNOXTOKEN service now reads the per-request target via resource instead of audience. Each value must be an absolute URI without a fragment (RFC 8707 §2 / RFC 3986 §4.3); a value that is not a valid absolute URI, or that carries a fragment, is rejected with 400 Bad Request / INVALID_RESOURCE. Repeated and comma-separated values are supported; whitespace is trimmed. The pluggable audience validators (static / whitelist / passthrough) are unchanged in behavior.

  2. Wire the RFC 8693 resource/audience body parameters into token exchange.
    The JWTProvider's TokenExchangeHandler now parses the optional resource/audience body params from the exchange request and conveys them to the downstream KNOXTOKEN service via a new shared request attribute (CommonTokenConstants.REQUESTED_AUDIENCES_REQUEST_ATTR), so they land in the minted token's aud claim. resource values are URI-validated (malformed → invalid_target); audience values are logical service names taken verbatim. When present, the body values take precedence over the resource query parameter.

  3. JSON-escape the caller-supplied resource value in the token error body.
    The token-issuance error echoed the caller-supplied value back in a hand-concatenated JSON body, so a value containing a " could break out of the JSON string. The {"error": ..., "code": ...} body is now rendered through JsonUtils (the same escaping the KNOX-3423/KNOX-3423: Switch to JSON error messages in Knox token validation paths #1354 filter-layer error path uses), keeping the existing {error, code} / ErrorCode shape.

Documentation in knox-site/docs/config_knox_token.md is updated to describe the resource parameter, the absolute-URI requirement, and the RFC 8707 mapping into the aud claim.

How was this patch tested?

Automated unit tests (all green, offline Maven build):

  • TokenExchangeHandlerTest — 21 tests, including 8 new ones covering resource/audience body-param parsing, comma-splitting, invalid-URI and fragment rejection as invalid_target, empty-value rejection, and the no-param case leaving the request attribute unset.
  • TokenServiceResourceTest — 101 tests, including new coverage for the resource query param, invalid-URI/fragment rejection, exchange-attribute precedence over the query param, and a regression test asserting a resource value containing double quotes yields a well-formed, parseable JSON error body with the value round-tripped intact.
  • JWTFederationFilterTokenExchangeTest — 56 tests, re-run to confirm no regression on the broader exchange path.

Checkstyle passes with 0 violations across gateway-spi, gateway-provider-security-jwt, and gateway-service-knoxtoken.

Integration Tests

No new integration test was added: the change is an extension of the existing token-exchange / dynamic-audience paths, which are covered comprehensively at the unit level, and the KnoxIDF federation broker flow (test_knoxidf.py / test_knoxidf_federation.py) already exercises the token-exchange handler this PR modifies. Because commit 2 touches the JWTProvider federation broker path, adding the test-federation label here before pushing, so the Keycloak-backed E2E federation suite runs against these changes.

@smolnar82

Copy link
Copy Markdown
Contributor Author

Cc. @hsheinblatt

@github-actions

github-actions Bot commented Sep 2, 2026

Copy link
Copy Markdown

Test Results

  5 files    5 suites   17s ⏱️
 87 tests  87 ✅ 0 💤 0 ❌
105 runs  105 ✅ 0 💤 0 ❌

Results for commit 13f57b2.

♻️ This comment has been updated with latest results.

smolnar82 and others added 5 commits September 3, 2026 17:23
…urce param

The KNOXTOKEN service now takes the requested token audience via the RFC 8707
`resource` query parameter instead of `audience`. Per RFC 8707 section 2 (and
RFC 3986 section 4.3) each `resource` value must be an absolute URI without a
fragment component; a query component is allowed. Invalid values are rejected
with 400 (new ErrorCode.INVALID_RESOURCE). The pluggable audience validators
(static/whitelist/passthrough) are unchanged and still resolve the `aud` claim;
only their input source changed. Docs and tests updated accordingly.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…hange

The JWTProvider's TokenExchangeHandler now reads the optional RFC 8693
section 2.1 resource/audience body parameters from the token-exchange
request and conveys them to the downstream KNOXTOKEN service, which mints
the token and resolves the aud claim through its configured audience
validator.

- resource values are validated as absolute URIs without a fragment
  (RFC 8707 section 2 / RFC 3986 section 4.3); a malformed value is
  rejected with the invalid_target error code.
- audience values are logical service names and are taken verbatim.
- Both parameters may be repeated and may carry comma-separated lists.
- The parsed values are stashed on the request via the new
  CommonTokenConstants.REQUESTED_AUDIENCES_REQUEST_ATTR attribute; when
  present they take precedence over the resource query parameter that
  KNOXTOKEN would otherwise honor.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…n error body

The token-issuance error for a rejected resource/audience echoed the
caller-supplied resource value back inside a hand-concatenated JSON body,
so a value containing a double quote (or other JSON metacharacter) could
break out of the JSON string and corrupt the response.

Render the {"error": ..., "code": ...} body through JsonUtils instead of
string concatenation, which escapes the embedded value the same way the
KNOX-3423 (apache#1354) filter-layer error path does. The {error, code} shape
and ErrorCode contract used by the token lifecycle responses are kept.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…urce docs

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…t exchange-specific

Address review feedback: the KNOXTOKEN service should be about issuing
tokens and not know about RFC 8693 token exchange. Rename the cross-layer
request attribute value from 'knox.token.exchange.requested.audiences' to
'knox.token.requested.audiences' and reword the CommonTokenConstants javadoc
and the TokenResource comment so the token service only knows that an
upstream component may pre-resolve the requested audiences (taking precedence
over the resource query param). The RFC 8693 specifics stay entirely within
TokenExchangeHandler, the producer of the attribute.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@smolnar82
smolnar82 merged commit 3cb11c6 into apache:master Sep 3, 2026
3 checks passed
@smolnar82
smolnar82 deleted the KNOX-3424 branch September 3, 2026 16:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants