You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
feat: add jwtValidationKeys filter for JWT validation with direct JWKS URL (#3922)
## Summary
- Add new `jwtValidationKeys` filter that verifies JWT Bearer tokens
using a JWKS URL directly, without requiring OIDC discovery via
`.well-known/openid-configuration`
- Reuses existing `jwtValidationFilter` — the new spec only provides an
alternative entry point that skips OIDC discovery
- Claims validation delegated to `oidcClaimsQuery` as per existing
convention
- Registered alongside `jwtValidation` in skipper.go
## Motivation
The existing `jwtValidation` filter only supports JWKS discovery via
`.well-known/openid-configuration`. Services like Google Chat bots sign
webhook requests with JWTs but publish their public keys at non-standard
JWKS endpoints without OIDC discovery support, making it impossible to
verify these tokens with the current filter.
## Usage
```
jwtValidationKeys("https://www.googleapis.com/service_accounts/v1/jwk/chat@system.gserviceaccount.com")
-> oidcClaimsQuery("/:@_:iss==\"chat@system.gserviceaccount.com\"")
-> oidcClaimsQuery("/:@_:aud==\"123456789\"")
```
Closes#3921
## Test plan
- [x] Spec validation (missing args, too many args, non-string args)
- [x] Valid token, expired token, missing sub claim
- [x] Missing/empty/malformed Bearer tokens
- [x] Algorithm none rejected
- [x] Existing jwtValidation tests still pass
---------
Signed-off-by: ivan-digital <root@ivan.digital>
Co-authored-by: ivan-digital <root@ivan.digital>
The filter works like [jwtValidation](#jwtvalidation) but takes a JWKS URL directly instead of
1687
+
discovering it via `/.well-known/openid-configuration`. This is useful for services that publish
1688
+
JWKS keys at non-standard endpoints, such as Google Chat service accounts.
1689
+
Unlike `jwtValidation`, the `sub` claim is not required — tokens without `sub` are accepted.
1690
+
1691
+
The filter stores token claims into the state bag where they can be used by [oidcClaimsQuery](#oidcclaimsquery), [forwardToken](#forwardtoken) or [forwardTokenField](#forwardtokenfield) filters.
0 commit comments