817927cb7d
schemas / check-release (pull_request) Successful in 1m57s
schemas / vulnerabilities (pull_request) Successful in 2m48s
schemas / check (pull_request) Successful in 8m17s
pre-commit / pre-commit (pull_request) Successful in 11m38s
schemas / build (pull_request) Successful in 5m31s
schemas / deploy-prod (pull_request) Has been skipped
- Use validator and jwks packages for JWT validation - Replace manual JWKS caching with jwks.NewCachingProvider - Add CustomClaims struct for https://unbound.se/roles claim - Rename TokenFromContext to ClaimsFromContext - Update middleware/auth.go to use new claims structure - Update tests to use core.SetClaims and validator.ValidatedClaims Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
84 lines
1.9 KiB
Go
84 lines
1.9 KiB
Go
package middleware
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"log"
|
|
"net/url"
|
|
|
|
jwtmiddleware "github.com/auth0/go-jwt-middleware/v3"
|
|
"github.com/auth0/go-jwt-middleware/v3/jwks"
|
|
"github.com/auth0/go-jwt-middleware/v3/validator"
|
|
)
|
|
|
|
// CustomClaims contains custom claims from the JWT token.
|
|
type CustomClaims struct {
|
|
Roles []string `json:"https://unbound.se/roles"`
|
|
}
|
|
|
|
// Validate implements the validator.CustomClaims interface.
|
|
func (c CustomClaims) Validate(_ context.Context) error {
|
|
return nil
|
|
}
|
|
|
|
type Auth0 struct {
|
|
domain string
|
|
audience string
|
|
}
|
|
|
|
func NewAuth0(audience, domain string, _ bool) *Auth0 {
|
|
return &Auth0{
|
|
domain: domain,
|
|
audience: audience,
|
|
}
|
|
}
|
|
|
|
type Response struct {
|
|
Message string `json:"message"`
|
|
}
|
|
|
|
func (a *Auth0) Middleware() *jwtmiddleware.JWTMiddleware {
|
|
issuer := fmt.Sprintf("https://%s/", a.domain)
|
|
|
|
issuerURL, err := url.Parse(issuer)
|
|
if err != nil {
|
|
log.Fatalf("failed to parse issuer URL: %v", err)
|
|
}
|
|
|
|
provider, err := jwks.NewCachingProvider(jwks.WithIssuerURL(issuerURL))
|
|
if err != nil {
|
|
log.Fatalf("failed to create JWKS provider: %v", err)
|
|
}
|
|
|
|
jwtValidator, err := validator.New(
|
|
validator.WithKeyFunc(provider.KeyFunc),
|
|
validator.WithAlgorithm(validator.RS256),
|
|
validator.WithIssuer(issuer),
|
|
validator.WithAudience(a.audience),
|
|
validator.WithCustomClaims(func() validator.CustomClaims {
|
|
return &CustomClaims{}
|
|
}),
|
|
)
|
|
if err != nil {
|
|
log.Fatalf("failed to create JWT validator: %v", err)
|
|
}
|
|
|
|
jwtMiddleware, err := jwtmiddleware.New(
|
|
jwtmiddleware.WithValidator(jwtValidator),
|
|
jwtmiddleware.WithCredentialsOptional(true),
|
|
)
|
|
if err != nil {
|
|
log.Fatalf("failed to create JWT middleware: %v", err)
|
|
}
|
|
|
|
return jwtMiddleware
|
|
}
|
|
|
|
func ClaimsFromContext(ctx context.Context) *validator.ValidatedClaims {
|
|
claims, err := jwtmiddleware.GetClaims[*validator.ValidatedClaims](ctx)
|
|
if err != nil {
|
|
return nil
|
|
}
|
|
return claims
|
|
}
|