refactor: 使用 go-oidc 验证 ID Token
This commit is contained in:
@@ -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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user