envoyproxy / envoyproxy/gateway
OIDC: make the forwarded access token header configurable
- Dominant language
- Go
- Stars
- 3k
- Forks
- 864
- Avg merge
- 2d 2h
- Merged PRs (30d)
- 140
Description
The below was generated using AI and I'll come back to clean up the description.
*Description*:
## What
Allow the OIDC access token to be forwarded to a configurable upstream header, the same way `forwardIDToken.header` works today.
## Why
Follow-up to #7343. That issue delivered configurable forwarding for the **ID token** (#9367), but the **access token** is still hardwired to `Authorization: Bearer `:
```go
// api/v1alpha1/oidc_types.go
// ForwardAccessToken indicates whether the Envoy should forward the access token
// via the Authorization header Bearer scheme to the upstream.
ForwardAccessToken *bool `json:"forwardAccessToken,omitempty"`
```
Forwarding both tokens at once already works (access token on Authorization, ID token on a custom header), so this is a symmetry/flexibility gap rather than a blocked use case. It matters when the upstream already uses Authorization for its own scheme, or when a backend expects the access token on a specific vendor header.
Originally raised by @tvandinther in https://github.com/envoyproxy/gateway/issues/7343#issuecomment-3511105788:
> It would be particularly useful to be able to forward both the ID token and access token at the same time to 2 different and configurable headers. Even if we could opt to forward the ID token, in the proposed changes we would then lose the access token. They both have unique use cases which warrant having them both forwarded.
Blocked on upstream Envoy
Envoy's oauth2 filter exposes the two tokens asymmetrically:
```
// api/envoy/extensions/filters/http/oauth2/v3/oauth.proto
bool forward_bearer_token = 7; // access token — no header field
OAuth2TokenForwarding forward_id_token = 31; // ID token — { string header = 1; }
```
OAuth2TokenForwarding already exists and is exactly the right shape. The upstream change is to add a parallel field at the next free number:
```
// Forward the OAuth2 access token to the upstream on a configurable header.
// Mutually exclusive with forward_bearer_token.
OAuth2TokenForwarding forward_access_token = 32;
```
plus the corresponding handling in source/extensions/filters/http/oauth2/filter.cc, matching how forward_id_token is applied. envoyproxy/envoy#45268 is the precedent to follow.
Until that lands and EG picks it up via a go-control-plane / Envoy image bump, there is no xDS field to translate into. This cannot be implemented in EG alone.
Proposed Envoy Gateway API
forwardAccessToken is already released as *bool, so it can't be retyped without breaking users. Two options, to be agreed before implementation:
Option A — sibling field (preferred):
oidc:
forwardAccessTokenTo:
header: X-Access-Token
Keeps forwardAccessToken: true working as shorthand for header: Authorization; the two are mutually exclusive via CEL. Symmetric with forwardIDToken, though the naming is a bit awkward.
Option B — reuse the existing field name with a union type. Cleaner surface, but needs care to stay backward compatible with the bool.
Either way the existing CEL rule on OIDCConfig (which keys on forwardAccessToken being a bool) needs reworking to cover the new combinations, including rejecting the same header for both tokens.
Implementation sketch (once unblocked)
Mirrors the ID token path almost exactly:
- api/v1alpha1/oidc_types.go — new field + CEL validation
- internal/ir/xds.go — IR field alongside ForwardIDTokenHeader
- internal/gatewayapi/securitypolicy.go — translation
- internal/xds/translator/oidc.go — set ForwardAccessToken on the oauth2 config, following the ForwardIdToken block
- Tests: CEL, gatewayapi testdata, xds testdata, e2e
- Docs + release note fragment
Small, low-risk PR — the entire cost is upstream.
/kind feature
Contributor guide
No contributing guide indexed for this repository
Research direction
Start with Envoy's oauth.proto and source/extensions/filters/http/oauth2/filter.cc, following envoyproxy/envoy#45268; this issue is blocked until the upstream configurable access-token field lands. Once available, trace the analogous ForwardIDToken path through api/v1alpha1/oidc_types.go, internal/ir/xds.go, internal/gatewayapi/securitypolicy.go, and internal/xds/translator/oidc.go, then run the listed CEL, gatewayapi, xDS, and e2e tests.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- go
- Domain
- api, authentication, backend
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 28/100