envoyproxy / envoyproxy/gateway
SecurityPolicy JWT claimToHeaders can't address claim names containing dots (e.g. URI-namespaced OIDC claims)
- Dominant language
- Go
- Stars
- 3k
- Forks
- 864
- Avg merge
- 2d 2h
- Merged PRs (30d)
- 140
Description
### Description
`SecurityPolicy.spec.jwt.providers[].claimToHeaders[].claim` is passed straight through to Envoy's `jwt_authn` filter as `claim_name`, which Envoy always splits on `.` to address nested claims.
This makes it impossible to extract any claim whose own name contains a dot — most commonly URI-namespaced custom claims emitted by OIDC providers (auth0 etc.), e.g. `https://example.com/claims/tenant_name`.
Envoy misinterprets the dots as a nested-object path, the lookup fails, and the header is silently never set (no error, no log).
Envoy Gateway does no transformation of the claim name — it forwards the string as-is to Envoy. The gap is in the `SecurityPolicy` CRD.
### Confirmed via xDS dump
```json
"claim_to_headers": [
{ "header_name": "Tenant-Name", "claim_name": "https://auth.example.com/claims/tenant_name" }
]
```
### Envoy already solves this but not included on SecurityPolicy CRD
Envoy's `jwt_authn` filter has a second field, [`claim_path`](https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/filters/http/jwt_authn/v3/config.proto#extensions-filters-http-jwt-authn-v3-jwtclaimtoheader), which takes an explicit list of path segments and matches each one literally against a JSON key — built for exactly this case:
```yaml
claim_to_headers:
- header_name: x-jwt-claim
claim_path:
- key: "https://example.com/claims/tenant_name"
```
`SecurityPolicy`'s `ClaimToHeader` type has no equivalent field today.
https://gateway.envoyproxy.io/docs/api/extension_types/#claimtoheader
### Proposed fix
Add an optional `claimPath []string` field to `ClaimToHeader`, mutually exclusive with `claim`, mapping 1:1 to Envoy's `claim_path` segments:
```go
type ClaimToHeader struct {
Header string `json:"header"`
Claim string `json:"claim,omitempty"` // existing, dot-split nested claim lookup
ClaimPath []string `json:"claimPath,omitempty"` // new, explicit segments for dotted/URI-namespaced claim names
}
```
Validate that exactly one of `claim`/`claimPath` is set per entry.
Existing configs using `claim` are unaffected.
### Repro
```yaml
claimToHeaders:
- claim: "https://example.com/claims/tenant_name"
header: Tenant-Name
```
A verified JWT containing that claim never populates `Tenant-Name`
Contributor guide
No contributing guide indexed for this repository
Research direction
Start at the SecurityPolicy CRD's ClaimToHeader type and trace its mapping to Envoy jwt_authn claim_to_headers, using the supplied xDS example as the reference. Check the existing validation and translation tests for this type. Done means claimPath maps to literal Envoy claim_path segments, claim and claimPath are mutually exclusive, and existing claim behavior remains unchanged.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- go, kubernetes
- Domain
- api, backend
- Issue type
- Feature
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 75/100