fix(auth): verify JWT signature to prevent cache-key forgery (GHSA-9gqw-h2rw-44wv)

The proxy derived per-user GraphQL cache keys from JWT claims without
verifying the token signature (CWE-345). A remote attacker could forge a
token that carried a victim's claim value and read the victim's cached
response.

This change adds opt-in signature verification behind JWT_VERIFY_SIGNATURE.
The flag defaults to false, so an upgrade without a config change keeps the
previous delegate-to-upstream behavior byte for byte.

When verification is on, the operator must set exactly one key source:
JWT_SECRET, JWT_PUBLIC_KEY, or JWT_JWKS_URL. The verifier pins the accepted
algorithms to the key family through WithValidMethods and a type-switched
keyfunc, and it refuses alg=none. This closes the algorithm-confusion class
of attack. A present but invalid token now returns 401. A missing
Authorization header stays anonymous.

Startup fails loudly when verification is on and the key source is absent or
unreadable, so the proxy can never boot half-configured.
This commit is contained in:
2026-08-17 13:51:00 +01:00
parent 99f0c844f0
commit 8258b3d99a
11 changed files with 881 additions and 36 deletions
+4
View File
@@ -3,6 +3,7 @@ module github.com/lukaszraczylo/graphql-monitoring-proxy
go 1.25.0
require (
github.com/MicahParks/keyfunc/v3 v3.8.1
github.com/VictoriaMetrics/metrics v1.44.0
github.com/alicebob/miniredis/v2 v2.33.0
github.com/avast/retry-go/v4 v4.7.0
@@ -10,6 +11,7 @@ require (
github.com/gofiber/contrib/v3/websocket v1.2.0
github.com/gofiber/fiber/v3 v3.3.0
github.com/gofrs/flock v0.13.0
github.com/golang-jwt/jwt/v5 v5.3.1
github.com/google/uuid v1.6.0
github.com/gookit/goutil v0.7.6
github.com/gorilla/websocket v1.5.3
@@ -32,6 +34,7 @@ require (
)
require (
github.com/MicahParks/jwkset v0.11.1 // indirect
github.com/alicebob/gopher-json v0.0.0-20200520072559-a9ecdc9d1d3a // indirect
github.com/andybalholm/brotli v1.2.1 // indirect
github.com/cenkalti/backoff/v5 v5.0.3 // indirect
@@ -68,6 +71,7 @@ require (
golang.org/x/sys v0.46.0 // indirect
golang.org/x/term v0.44.0 // indirect
golang.org/x/text v0.39.0 // indirect
golang.org/x/time v0.15.0 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20260618152121-87f3d3e198d3 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20260618152121-87f3d3e198d3 // indirect
google.golang.org/protobuf v1.36.11 // indirect