A Go library for JWT validation with automatic JWKS fetching and key rotation. Includes HTTP middleware.
- Minimal Config — Get up and running with just your audience + tenant ID or genric discovery endpoint
- HTTP Middleware — Drop-in
http.Handlermiddleware for protected routes - Generic OIDC — Works with Auth0, Okta, or any OIDC provider
go get github.com/intility/go-jwksfetcher, _ := jwks.NewJWKSFetcher(jwks.EntraID{TenantID: "your-tenant-id"})
fetcher.Start(ctx)
validator, _ := fetcher.NewJWTValidator("api://your-audience")
middleware := jwks.JWTMiddleware(validator)
mux.Handle("/protected", middleware(yourHandler))The validator uses smart defaults:
- Issuer: Automatically extracted from the OIDC discovery document
- Signing methods: RS256
See the examples folder for complete runnable examples:
- basic - Standard JWT validation with HTTP middleware
- custom-claims - Using generic claims types for application-specific JWT fields
The fetcher uses secure defaults (HTTPS required, TLS 1.2+, 24h refresh). Override when needed:
fetcher, err := jwks.NewJWKSFetcher(
jwks.Generic{DiscoveryURL: "https://auth.example.com/.well-known/openid-configuration"},
jwks.WithFetchInterval(12 * time.Hour), // Override refresh interval (default: 24h)
jwks.WithAllowedJWKSHosts([]string{"auth.example.com"}), // Restrict JWKS to specific hosts
jwks.WithMicrosoftHosts(), // Preset for Microsoft Entra ID hosts
jwks.WithRequireHTTPS(false), // Allow HTTP (default: true)
jwks.WithTLSConfig(customTLSConfig), // Custom TLS configuration
jwks.WithMaxResponseSize(512 * 1024), // Limit response size (default: 1MB)
jwks.WithMaxKeysCount(50), // Limit key count (default: 100)
)The validator uses smart defaults (issuer from discovery, RS256 signing). Override when needed:
validator, err := fetcher.NewJWTValidator("api://my-app",
jwks.WithIssuers("https://custom-issuer"), // Override discovery issuer
jwks.WithAdditionalAudiences("api://other"), // Add more audiences
jwks.WithValidMethods("RS384"), // Override signing methods
)This library implements several security best practices by default:
Protect against SSRF attacks by restricting which hosts can serve JWKS:
fetcher, err := jwks.NewJWKSFetcher(
jwks.Generic{DiscoveryURL: "https://auth.example.com/.well-known/openid-configuration"},
jwks.WithAllowedJWKSHosts([]string{"auth.example.com", "backup-auth.example.com"}),
)For Microsoft Entra ID, use the preset configuration:
fetcher, err := jwks.NewJWKSFetcher(
jwks.EntraID{TenantID: "your-tenant-id"},
jwks.WithMicrosoftHosts(), // Allows only Microsoft's auth domains
)- HTTPS Required: By default, only HTTPS URLs are accepted for JWKS endpoints. This can be disabled for testing/internal environments using
WithRequireHTTPS(false) - TLS 1.2+: Minimum TLS version 1.2 is enforced for all HTTPS connections
- Response Size Limits: JWKS responses are limited to 1MB by default to prevent memory exhaustion attacks
- Key Count Limits: Maximum of 100 keys per JWKS to prevent resource exhaustion
- Fetcher retrieves public keys from the OIDC discovery endpoint and refreshes them periodically (default: 24h)
- Validator uses these keys to verify JWT signatures and validate claims (issuer, audience, expiry)
- Middleware extracts the Bearer token from
Authorizationheader and validates it
For validating JWTs outside of HTTP handlers:
claims, err := validator.ValidateJWT(ctx, tokenString)
if err != nil {
if errors.Is(err, jwks.ErrInvalidAud) {
// Handle invalid audience
}
return err
}
fmt.Printf("User: %s\n", claims.Email)Error types: ErrInvalidToken, ErrInvalidAud, ErrInvalidIss
Currently only RSA based encryption algorithms are supported.