MCPcopy Create free account
hub / github.com/bytebase/bytebase / ValidateToken

Function ValidateToken

backend/plugin/idp/wif/wif.go:25–78  ·  view source on GitHub ↗

ValidateToken validates an OIDC token against a workload identity configuration.

(ctx context.Context, tokenString string, config *storepb.WorkloadIdentityConfig)

Source from the content-addressed store, hash-verified

23
24// ValidateToken validates an OIDC token against a workload identity configuration.
25func ValidateToken(ctx context.Context, tokenString string, config *storepb.WorkloadIdentityConfig) (*TokenClaims, error) {
26 // Parse the token
27 token, err := jwt.ParseSigned(tokenString, []jose.SignatureAlgorithm{jose.RS256, jose.ES256})
28 if err != nil {
29 return nil, errors.Wrap(err, "failed to parse token")
30 }
31
32 // Get JWKS from issuer
33 jwks, err := FetchJWKS(ctx, config.IssuerUrl)
34 if err != nil {
35 return nil, errors.Wrap(err, "failed to fetch JWKS")
36 }
37
38 // Use jwt.Claims which handles audience as both string and []string
39 var registeredClaims jwt.Claims
40 if err := token.Claims(jwks, &registeredClaims); err != nil {
41 return nil, errors.Wrap(err, "failed to verify token signature")
42 }
43
44 // Convert to our TokenClaims format
45 claims := &TokenClaims{
46 Issuer: registeredClaims.Issuer,
47 Subject: registeredClaims.Subject,
48 Audience: registeredClaims.Audience,
49 }
50 if registeredClaims.Expiry != nil {
51 claims.Expiry = registeredClaims.Expiry.Time().Unix()
52 }
53 if registeredClaims.IssuedAt != nil {
54 claims.IssuedAt = registeredClaims.IssuedAt.Time().Unix()
55 }
56
57 // Validate issuer
58 if claims.Issuer != config.IssuerUrl {
59 return nil, errors.Errorf("issuer mismatch: expected %q, got %q", config.IssuerUrl, claims.Issuer)
60 }
61
62 // Validate audience (skip if no allowed audiences configured)
63 if len(config.AllowedAudiences) > 0 && !validateAudience(claims.Audience, config.AllowedAudiences) {
64 return nil, errors.Errorf("audience mismatch: token has %v, allowed %v", claims.Audience, config.AllowedAudiences)
65 }
66
67 // Validate subject pattern
68 if !matchSubjectPattern(claims.Subject, config.SubjectPattern) {
69 return nil, errors.Errorf("subject mismatch: expected pattern %q, got %q", config.SubjectPattern, claims.Subject)
70 }
71
72 // Validate expiry
73 if time.Now().Unix() > claims.Expiry {
74 return nil, errors.New("token has expired")
75 }
76
77 return claims, nil
78}
79
80func validateAudience(tokenAudience []string, allowedAudiences []string) bool {
81 for _, allowed := range allowedAudiences {

Callers 1

ExchangeTokenMethod · 0.92

Calls 4

FetchJWKSFunction · 0.85
validateAudienceFunction · 0.85
matchSubjectPatternFunction · 0.85
ErrorfMethod · 0.80

Tested by

no test coverage detected