Add RFC 7523 JWT Bearer grant package#5262
Merged
Merged
Conversation
Add pkg/oauthproto/jwtbearer, a self-contained client for the JWT Bearer token grant defined by RFC 7523 Section 2.1. The grant exchanges a signed JWT assertion for an OAuth 2.0 access token at a target authorization server's token endpoint. TokenURL validation reuses pkg/networking.ValidateEndpointURL plus host, fragment, and userinfo checks to enforce RFC 6749 Section 3.2 (token endpoints must use TLS) and to reject URLs that smuggle credentials in the URL itself. The token_type field in the success response is validated as required by RFC 6749 Section 5.1. HTTP error responses are returned as *oauth2.RetrieveError (from golang.org/x/oauth2) with the raw Body scrubbed before return, matching pkg/oauthproto/tokenexchange's stricter behavior so error strings cannot leak upstream content into logs. Client authentication is HTTP Basic per RFC 6749 Section 2.3.1; the package targets confidential clients per XAA / ID-JAG §8.1 and does not support public-client identification via a body client_id parameter. Also add the GrantTypeJWTBearer URN constant to pkg/oauthproto, the first consumer of which is this package. The jwtbearer package is the Step B primitive used by the XAA (ID-JAG) strategy. It has no XAA-specific behaviour at this layer and works for any RFC 7523 JWT-Bearer exchange with a confidential client.
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #5262 +/- ##
==========================================
+ Coverage 68.02% 68.03% +0.01%
==========================================
Files 616 617 +1
Lines 63005 63098 +93
==========================================
+ Hits 42857 42927 +70
- Misses 16945 16962 +17
- Partials 3203 3209 +6 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
rdimitrov
approved these changes
May 12, 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.
Summary
pkg/oauthproto/jwtbearerexposes aConfigandTokenSourcemodeled on the siblingpkg/oauthproto/tokenexchangeand built on the sharedpkg/oauthprotohelpers (NewFormRequest,DoTokenRequest,ParseTokenResponse,Redact).TokenURLvalidation reusespkg/networking.ValidateEndpointURL(RFC 6749 §3.2 — TLS required, localhost exception) and adds host, fragment, and embedded-userinfo checks to reject URLs that smuggle credentials.*oauth2.RetrieveErrorwithBodyscrubbed before return, matching the stricter behavior ofpkg/oauthproto/tokenexchangeso error strings cannot leak raw upstream content into logs.client_id-in-body is intentionally not supported.GrantTypeJWTBearerURN constant topkg/oauthproto.Refs #5218
Type of change
Test plan
task test)task lint-fix)go test ./pkg/oauthproto/jwtbearer/covers: TokenURL validation (scheme, host, fragment, userinfo, required fields),String()redaction of secrets and assertion, success path with and without scopes, and the jwtbearer-specific error paths (assertion-provider error, RetrieveError unwrap + Body scrub, emptytoken_typerejection per RFC 6749 §5.1).Does this introduce a user-facing change?
No. This is a library-internal primitive; no CLI surface, CRD, or runtime behavior changes yet. The first user-facing consumer (the XAA / ID-JAG strategy) will land in a follow-up PR.
Implementation plan
Approved implementation plan
Package scope:
oauthproto.NewFormRequestper RFC 6749 §2.3.1. No JWT client auth (RFC 7523 §2.2), noclient_secret_post, no body-onlyclient_id— these are out of scope for the XAA consumer and YAGNI for now.pkg/oauthproto/tokenexchange:ConfigwithValidate()/String()/TokenSource(ctx), internaltokenSourcewithToken().buildFormDatais private and only emits the three RFC 7523 §2.1 fields (grant_type,assertion, optionalscope).Security posture (informed by parallel multi-agent review):
TokenURLwith embedded userinfo to prevent credential leakage to the AS / via logs.RetrieveError.Bodybefore return so logged errors cannot include raw upstream content (matchestokenexchange).Redact()used inString()forClientSecretand the assertion-presence marker.networking.ValidateEndpointURL(localhost dev exception).Validation tightening on top of
oauthproto.ParseTokenResponse:token_typeis rejected at the jwtbearer layer (RFC 6749 §5.1) since the shared helper is intentionally permissive.Test scope discipline:
oauthproto.ParseTokenResponseorNewFormRequestbranches alone are out of scope and intentionally not tested here (those have their own tests).Special notes for reviewers
pkg/oauthproto/tokenexchange/exchange.gois the closest sibling and a useful reference for parallel structure; one minor follow-up worth doing later is normalizing the error-message prefix in both packages (jwtbearer:/tokenexchange:).🤖 Generated with Claude Code