更新依赖项,优化 OAuth2 服务,添加 PKCE 支持,增强 OIDC 处理器,新增客户端注册和令牌管理端点,改进数据库模型以支持新功能。

This commit is contained in:
2025-04-17 01:25:46 +08:00
parent 0368547137
commit a3f3cc17cf
13 changed files with 738 additions and 70 deletions

114
services/token.go Normal file
View File

@@ -0,0 +1,114 @@
package services
import (
"errors"
"time"
"github.com/golang-jwt/jwt/v4"
"gorm.io/gorm"
)
type TokenService struct {
db *gorm.DB
keyManager *KeyManager
}
type TokenInfo struct {
Active bool `json:"active"`
Scope string `json:"scope,omitempty"`
ClientID string `json:"client_id,omitempty"`
Username string `json:"username,omitempty"`
TokenType string `json:"token_type,omitempty"`
Exp int64 `json:"exp,omitempty"`
Iat int64 `json:"iat,omitempty"`
Nbf int64 `json:"nbf,omitempty"`
Sub string `json:"sub,omitempty"`
Aud string `json:"aud,omitempty"`
Iss string `json:"iss,omitempty"`
Jti string `json:"jti,omitempty"`
}
type RevokedToken struct {
gorm.Model
Token string `gorm:"uniqueIndex;not null"`
ExpiresAt time.Time `gorm:"not null"`
}
func NewTokenService(db *gorm.DB, keyManager *KeyManager) *TokenService {
return &TokenService{
db: db,
keyManager: keyManager,
}
}
func (s *TokenService) RevokeToken(token, tokenTypeHint string) error {
// 验证令牌
claims, err := s.parseToken(token)
if err != nil {
return err
}
// 保存到撤销列表
revokedToken := &RevokedToken{
Token: token,
ExpiresAt: time.Unix(claims["exp"].(int64), 0),
}
return s.db.Create(revokedToken).Error
}
func (s *TokenService) IntrospectToken(token, tokenTypeHint string) (*TokenInfo, error) {
// 检查令牌是否被撤销
var revokedToken RevokedToken
if err := s.db.Where("token = ?", token).First(&revokedToken).Error; err == nil {
return &TokenInfo{Active: false}, nil
}
// 解析令牌
claims, err := s.parseToken(token)
if err != nil {
return &TokenInfo{Active: false}, nil
}
// 检查令牌是否过期
exp := time.Unix(claims["exp"].(int64), 0)
if time.Now().After(exp) {
return &TokenInfo{Active: false}, nil
}
// 构建令牌信息
info := &TokenInfo{
Active: true,
Scope: claims["scope"].(string),
ClientID: claims["iss"].(string),
TokenType: "Bearer",
Exp: claims["exp"].(int64),
Iat: claims["iat"].(int64),
Sub: claims["sub"].(string),
}
return info, nil
}
func (s *TokenService) parseToken(token string) (jwt.MapClaims, error) {
parsedToken, err := jwt.Parse(token, func(token *jwt.Token) (interface{}, error) {
if _, ok := token.Method.(*jwt.SigningMethodRSA); !ok {
return nil, errors.New("unexpected signing method")
}
return s.keyManager.GetPrivateKey().Public(), nil
})
if err != nil {
return nil, err
}
if claims, ok := parsedToken.Claims.(jwt.MapClaims); ok && parsedToken.Valid {
return claims, nil
}
return nil, errors.New("invalid token")
}
func (s *TokenService) AutoMigrate() error {
return s.db.AutoMigrate(&RevokedToken{})
}