// Verify a CodeB JWT locally in Go. // Signed with RS256 against the tenant JWKS. European Digital Identity // Wallet id_tokens are validated the same way. // [jwt-validation-cookbook 2026-07-23] // // go get github.com/golang-jwt/jwt/v5 // go get github.com/MicahParks/keyfunc/v3 package main import ( "context" "fmt" "os" "time" "github.com/MicahParks/keyfunc/v3" "github.com/golang-jwt/jwt/v5" ) const ( Issuer = "https://" Audience = "" ) func verify(token string) (jwt.MapClaims, error) { // keyfunc fetches JWKS once, caches in memory, refreshes on kid-miss. k, err := keyfunc.NewDefaultCtx(context.Background(), []string{Issuer + "/.well-known/jwks.json"}) if err != nil { return nil, err } t, err := jwt.Parse(token, k.Keyfunc, jwt.WithValidMethods([]string{"RS256"}), jwt.WithIssuer(Issuer), jwt.WithAudience(Audience), jwt.WithLeeway(5*time.Second), ) if err != nil { return nil, err } return t.Claims.(jwt.MapClaims), nil } func main() { c, err := verify(os.Args[1]) if err != nil { fmt.Println("verify failed:", err) os.Exit(1) } fmt.Printf("sub = %v\nrole = %v\n", c["sub"], c["role"]) } // RFCs: 7519 (JWT), 7517 (JWK), 7518 (JWA).