refactor: 使用 go-oidc 验证 ID Token

This commit is contained in:
2026-07-14 11:11:48 +08:00
parent 053bc260c7
commit 85d72a1c8c
7 changed files with 91 additions and 69 deletions
+37
View File
@@ -43,6 +43,7 @@ type OIDCPublicClient struct {
mu sync.Mutex
oauth2Config *oauth2.Config
metadata oidcClientDiscovery
idVerifier *oidc.IDTokenVerifier
}
type oidcClientDiscovery struct {
@@ -112,6 +113,37 @@ func (c *OIDCPublicClient) Refresh(ctx context.Context, refreshToken string) (OI
return oidcTokenResponse(token)
}
func (c *OIDCPublicClient) VerifyIDToken(ctx context.Context, raw, expectedNonce string) (string, error) {
expectedNonce = strings.TrimSpace(expectedNonce)
if strings.TrimSpace(raw) == "" || expectedNonce == "" {
return "", oidcUnauthorized("ID token validation context is invalid", nil)
}
if _, _, err := c.configuration(ctx); err != nil {
return "", oidcUnauthorized("ID token provider discovery failed", err)
}
c.mu.Lock()
verifier := c.idVerifier
c.mu.Unlock()
if verifier == nil {
return "", oidcUnauthorized("ID token verifier is unavailable", nil)
}
token, err := verifier.Verify(c.requestContext(ctx), raw)
if err != nil {
return "", oidcUnauthorized("ID token signature or registered claims are invalid", nil)
}
if token.Subject == "" || token.Nonce != expectedNonce {
return "", oidcUnauthorized("ID token subject or nonce is invalid", nil)
}
var claims map[string]any
if err := token.Claims(&claims); err != nil {
return "", oidcUnauthorized("ID token claims are invalid", nil)
}
if _, ok := numericDateClaim(claims["nbf"]); !ok {
return "", oidcUnauthorized("ID token nbf is missing", nil)
}
return token.Subject, nil
}
func (c *OIDCPublicClient) RevokeRefreshToken(ctx context.Context, refreshToken string) error {
if strings.TrimSpace(refreshToken) == "" {
return nil
@@ -197,11 +229,16 @@ func (c *OIDCPublicClient) configuration(ctx context.Context) (*oauth2.Config, o
ClientID: c.config.ClientID, RedirectURL: c.config.RedirectURI,
Endpoint: endpoint, Scopes: append([]string(nil), c.config.Scopes...),
}
verifierContext := oidc.ClientContext(context.Background(), c.client)
idVerifier := provider.VerifierContext(verifierContext, &oidc.Config{
ClientID: c.config.ClientID, SupportedSigningAlgs: []string{oidc.RS256, oidc.ES256},
})
c.mu.Lock()
defer c.mu.Unlock()
if c.oauth2Config == nil {
c.oauth2Config = config
c.metadata = metadata
c.idVerifier = idVerifier
}
return c.oauth2Config, c.metadata, nil
}