package identity import ( "context" "errors" "strings" "github.com/coreos/go-oidc/v3/oidc" ) var ErrInvalidToken = errors.New("invalid access token") type TokenVerifier interface { Verify(context.Context, string) (Principal, error) } type OIDCVerifier struct { verifier *oidc.IDTokenVerifier } func NewOIDCVerifier(ctx context.Context, issuerURL, jwksURL, audience string) *OIDCVerifier { keySet := oidc.NewRemoteKeySet(ctx, jwksURL) return &OIDCVerifier{ verifier: oidc.NewVerifier(issuerURL, keySet, &oidc.Config{ClientID: audience}), } } func (v *OIDCVerifier) Verify(ctx context.Context, rawToken string) (Principal, error) { rawToken = strings.TrimSpace(rawToken) if rawToken == "" { return Principal{}, ErrInvalidToken } token, err := v.verifier.Verify(ctx, rawToken) if err != nil { return Principal{}, ErrInvalidToken } var claims struct { Name string `json:"name"` PreferredUsername string `json:"preferred_username"` } if err := token.Claims(&claims); err != nil { return Principal{}, ErrInvalidToken } if token.Issuer == "" || token.Subject == "" { return Principal{}, ErrInvalidToken } return Principal{ Issuer: token.Issuer, Subject: token.Subject, DisplayName: claims.Name, PreferredUsername: claims.PreferredUsername, }, nil }