Documentation
¶
Index ¶
- Constants
- Variables
- func BuildDPoPBoundAccessTokenURI(fullURL string) (string, error)
- func BuildRedirectURL(baseURI, code, state string) (string, error)
- func BuildRequestURI(r *http.Request) string
- func ComputeJKT(jwk map[string]interface{}) (string, error)
- func ComputePKCEChallenge(method, verifier string) (string, error)
- func DPoPMiddleware(cache ReplayCache, required bool) func(http.Handler) http.Handler
- func DPoPOptionalMiddleware(cache ReplayCache) func(http.Handler) http.Handler
- func DPoPProtectedEndpoints() []string
- func DPoPRequiredMiddleware(cache ReplayCache) func(http.Handler) http.Handler
- func DecodeJSON(r io.Reader, v any) error
- func DeviceAuthorized(ctx context.Context, storage Storage, req *DeviceAuthorizedRequest) error
- func DeviceDenied(ctx context.Context, storage Storage, userCode string) error
- func EndSession(ctx context.Context, storage Storage, verifier TokenVerifier, ...) (string, error)
- func ExtractDPoPJKT(ctx context.Context) string
- func GeneratePKCEVerifier() (string, error)
- func GetSigningMethod(key crypto.PrivateKey) jwt.SigningMethod
- func Hash(method jwt.SigningMethod, str string) (string, error)
- func IsConfidentialClient(method string) bool
- func LoadTokenSecret() ([]byte, error)
- func ParseECDSAPublicKeyFromJWK(jwk *JSONWebKey) (*ecdsa.PublicKey, error)
- func ParseEd25519PublicKeyFromJWK(jwk *JSONWebKey) (ed25519.PublicKey, error)
- func ParseRSAPublicKeyFromJWK(jwk *JSONWebKey) (*rsa.PublicKey, error)
- func RandomString(n int) (string, error)
- func RefreshTokenRevoke(ctx context.Context, storage TokenStorage, secretManager *SecretManager, ...) error
- func RegisterMetrics()
- func ResponseAuthorized(ctx context.Context, storage AuthCodeStorage, req *AuthorizeRequest, ...) (string, error)
- func RevokeAccessToken(ctx context.Context, storage RevocationStorage, verifier TokenVerifier, ...) error
- func RevokeToken(ctx context.Context, storage Storage, secretManager *SecretManager, ...) error
- func SaveKey(path string, key Key, password []byte) error
- func SetServerTimeHeader(w http.ResponseWriter)
- func ShouldUseDPoP(path string) bool
- func UnregisterClient(ctx context.Context, storage ClientStorage, clientIDStr string) error
- func ValidateKeySecurity(key Key) error
- func ValidateRegistrationRequest(req *ClientRegistrationRequest, allowedSchemes map[string]struct{}) error
- func ValidateScopes(allowedScopeStr, requestedScopeStr string) error
- func ValidateStructuredRefreshToken(ctx context.Context, sm *SecretManager, token RefreshToken) error
- func ValidateURN(uri string) error
- func VerifyDPoPProof(ctx context.Context, req *http.Request, w http.ResponseWriter, ...) (jkt string, err error)
- func VerifyPKCE(challenge, method, verifier string) error
- type AccessToken
- type AccessTokenClaims
- type AuthCodeSession
- type AuthCodeStorage
- type AuthorizeRequest
- type BinaryUUID
- type Cache
- type ClientCache
- type ClientFactory
- type ClientMetadata
- func (c *ClientMetadata) Deserialize(data string) error
- func (c *ClientMetadata) GetGrantTypes() []string
- func (c *ClientMetadata) GetID() BinaryUUID
- func (c *ClientMetadata) GetRedirectURIs() []string
- func (c *ClientMetadata) GetScope() string
- func (c *ClientMetadata) IsConfidential() bool
- func (c *ClientMetadata) Metadata() *ClientMetadata
- func (c *ClientMetadata) Serialize() (string, error)
- func (ClientMetadata) TableName() string
- func (c *ClientMetadata) ValidateSecret(ctx context.Context, hasher Hasher, secret string) error
- type ClientRegistrationRequest
- type ClientRegistrationResponse
- type ClientStorage
- type ClientUpdateRequest
- type ClientVerifier
- type Code
- type DPoPClaims
- type DPoPProof
- type DPoPTimeSkewError
- type DPoPTimeSkewInfo
- type DeviceAuthorizationRequest
- type DeviceAuthorizationResponse
- type DeviceAuthorizedRequest
- type DeviceCodeSession
- type DeviceCodeStorage
- type Discovery
- type DistributedLock
- type DpopContextKey
- type EndSessionRequest
- type Error
- func AccessDeniedError(description string) *Error
- func AuthorizationPendingError(description string) *Error
- func ExpiredTokenError(description string) *Error
- func InvalidClientError(description string) *Error
- func InvalidGrantError(description string) *Error
- func InvalidRequestError(description string) *Error
- func InvalidScopeError(description string) *Error
- func NewError(code string, description string, statusCode int) *Error
- func ServerError(description string) *Error
- func ServerErrorWithDescription(description string) *Error
- func SlowDownError(description string) *Error
- func TemporarilyUnavailableError(description string) *Error
- func UnauthorizedClientError(description string) *Error
- func UnsupportedGrantTypeError(description string) *Error
- type GCWorker
- type Hash256
- type Hasher
- type IDToken
- type IDTokenClaims
- type IntrospectionRequest
- type IntrospectionResponse
- type Issuer
- func (g *Issuer) IssueClientCredentialsToken(ctx context.Context, req *IssuerRequest) (*IssuerResponse, error)
- func (g *Issuer) IssueOAuthTokens(ctx context.Context, req *IssuerRequest) (*IssuerResponse, error)
- func (g *Issuer) IssueOIDCTokens(ctx context.Context, req *IssuerRequest) (*IssuerResponse, error)
- func (g *Issuer) IssuePasswordResetAccessToken(ctx context.Context, req *IssuerRequest) (*IssuerResponse, error)
- func (i *Issuer) Issuer() string
- func (g *Issuer) RefreshOAuthTokens(ctx context.Context, req *IssuerRequest) (*IssuerResponse, error)
- func (g *Issuer) RefreshOIDCTokens(ctx context.Context, req *IssuerRequest) (*IssuerResponse, error)
- func (i *Issuer) SecretManager() *SecretManager
- type IssuerConfig
- type IssuerRequest
- type IssuerResponse
- func DeviceTokenExchange(ctx context.Context, storage Storage, issuer *Issuer, req *TokenRequest) (*IssuerResponse, error)
- func ExchangeClientCredentials(ctx context.Context, storage ClientStorage, hasher Hasher, issuer *Issuer, ...) (*IssuerResponse, error)
- func ExchangeCode(ctx context.Context, storage Storage, hasher Hasher, issuer *Issuer, ...) (*IssuerResponse, error)
- func PasswordGrant(ctx context.Context, storage Storage, hasher Hasher, issuer *Issuer, ...) (*IssuerResponse, error)
- func RefreshTokens(ctx context.Context, storage Storage, secretManager *SecretManager, ...) (*IssuerResponse, error)
- type JSONWebKey
- type JSONWebKeySet
- type JWK
- type Key
- type KeyManager
- func (km *KeyManager) Add(ctx context.Context, key Key) (string, error)
- func (km *KeyManager) ExportJWKS(ctx context.Context) (*JSONWebKeySet, error)
- func (km *KeyManager) Generate(ctx context.Context, kty KeyType, setAsSigning bool) (string, error)
- func (km *KeyManager) GetKey(ctx context.Context, kid string) (crypto.PublicKey, error)
- func (km *KeyManager) GetKeyInternal(ctx context.Context, kid string) (Key, error)
- func (km *KeyManager) GetSigningKey(ctx context.Context) (string, Key, error)
- func (km *KeyManager) JWKGetSigning(ctx context.Context) (string, error)
- func (km *KeyManager) ListKeys(ctx context.Context) ([]string, error)
- func (km *KeyManager) RemoveKey(ctx context.Context, kid string) error
- func (km *KeyManager) SetSigningKeyID(ctx context.Context, kid string) error
- type KeyProvider
- type KeyRotationConfig
- type KeyRotationScheduler
- type KeySource
- type KeyStorage
- type KeyType
- type ListQuery
- type MemoryKeyProvider
- func (m *MemoryKeyProvider) AddKey(kid string, key []byte) error
- func (m *MemoryKeyProvider) CleanupExpiredKeys(ctx context.Context) int
- func (m *MemoryKeyProvider) GetActiveKey(ctx context.Context) (string, []byte, error)
- func (m *MemoryKeyProvider) GetKey(ctx context.Context, kid string) ([]byte, error)
- func (m *MemoryKeyProvider) ListKeys(ctx context.Context) (map[string][]byte, error)
- func (m *MemoryKeyProvider) RemoveKey(kid string) error
- func (m *MemoryKeyProvider) RotateKey(newKID string, newKey []byte, gracePeriod time.Duration) error
- func (m *MemoryKeyProvider) SetActiveKey(kid string) error
- type PARRequest
- type PARResponse
- type PARStorage
- type Persistence
- type RefreshToken
- type RefreshTokenSession
- type RegisteredClient
- func AuthenticateClient(ctx context.Context, storage ClientStorage, clientIDStr, clientSecret string, ...) (RegisteredClient, error)
- func ListClient(ctx context.Context, storage ClientStorage, query ListQuery) ([]RegisteredClient, error)
- func RequestAuthorize(ctx context.Context, storage Storage, req *AuthorizeRequest) (RegisteredClient, error)
- type RemoteKeySet
- type RemoteKeySetOption
- type ReplayCache
- type ResourceVerifier
- type RevocationRequest
- type RevocationStorage
- type SecretBytes
- type SecretManager
- func (s *SecretManager) AddKey(id string, hexSecret string) error
- func (s *SecretManager) CleanupExpiredKeys() (int, error)
- func (s *SecretManager) GetSigningKey(ctx context.Context) ([]byte, string)
- func (s *SecretManager) GetVerificationKey(ctx context.Context, kid string) ([]byte, error)
- func (s *SecretManager) RotateKey(newKID string, newHexSecret string, gracePeriod time.Duration) error
- func (s *SecretManager) SetActiveKey(kid string) error
- type SecretString
- type Server
- func (s *Server) ClientUpdate(ctx context.Context, req *ClientUpdateRequest) (*ClientRegistrationResponse, error)
- func (s *Server) Config() *ServerConfig
- func (s *Server) DeviceAuthorization(ctx context.Context, req *DeviceAuthorizationRequest) (*DeviceAuthorizationResponse, error)
- func (s *Server) Discovery() *Discovery
- func (s *Server) EndSession(ctx context.Context, req *EndSessionRequest) (string, error)
- func (s *Server) Exchange(ctx context.Context, req *TokenRequest) (resp *IssuerResponse, err error)
- func (s *Server) GetUserInfo(ctx context.Context, claims *AccessTokenClaims) (*UserInfo, error)
- func (s *Server) Introspect(ctx context.Context, tokenStr, clientIDStr, clientSecret string) (*IntrospectionResponse, error)
- func (s *Server) Issuer() *Issuer
- func (s *Server) KeyManager() *KeyManager
- func (s *Server) ListClient(ctx context.Context, query ListQuery) ([]RegisteredClient, error)
- func (s *Server) ParseAccessToken(ctx context.Context, tokenStr string) (*AccessTokenClaims, error)
- func (s *Server) PushedAuthorization(ctx context.Context, req *PARRequest) (*PARResponse, error)
- func (s *Server) RegisterClient(ctx context.Context, req *ClientRegistrationRequest) (*ClientRegistrationResponse, error)
- func (s *Server) RequestAuthorize(ctx context.Context, req *AuthorizeRequest) (client RegisteredClient, err error)
- func (s *Server) ResponseAuthorized(ctx context.Context, req *AuthorizeRequest) (redirectURL string, err error)
- func (s *Server) RevokeToken(ctx context.Context, req *RevocationRequest) error
- func (s *Server) SecretManager() *SecretManager
- func (s *Server) StartBackgroundWorkers(ctx context.Context)
- func (s *Server) StopBackgroundWorkers()
- func (s *Server) UnregisterClient(ctx context.Context, clientIDStr string) error
- func (s *Server) ValidateKeys(ctx context.Context) error
- func (s *Server) VerifyAccessToken(ctx context.Context, tokenStr string) (*AccessTokenClaims, error)
- type ServerConfig
- type StaticKeySet
- type Storage
- type StringSlice
- type TieredStorage
- func (s *TieredStorage) ClientCreate(ctx context.Context, metadata *ClientMetadata) (RegisteredClient, error)
- func (s *TieredStorage) ClientDeleteByID(ctx context.Context, clientID BinaryUUID) error
- func (s *TieredStorage) ClientGetByID(ctx context.Context, clientID BinaryUUID) (RegisteredClient, error)
- func (s *TieredStorage) ClientListAll(ctx context.Context, query ListQuery) ([]RegisteredClient, error)
- func (s *TieredStorage) ClientListByOwner(ctx context.Context, ownerID BinaryUUID, query ListQuery) ([]RegisteredClient, error)
- func (s *TieredStorage) ClientUpdate(ctx context.Context, metadata *ClientMetadata) (RegisteredClient, error)
- func (s *TieredStorage) JWKDelete(ctx context.Context, kid string) error
- func (s *TieredStorage) JWKGet(ctx context.Context, kid string) (jwk.Key, error)
- func (s *TieredStorage) JWKGetSigning(ctx context.Context) (string, error)
- func (s *TieredStorage) JWKList(ctx context.Context) ([]jwk.Key, error)
- func (s *TieredStorage) JWKMarkSigning(ctx context.Context, kid string) error
- func (s *TieredStorage) JWKSave(ctx context.Context, key jwk.Key) error
- func (s *TieredStorage) RefreshTokenCreate(ctx context.Context, session *RefreshTokenSession) error
- func (s *TieredStorage) RefreshTokenGet(ctx context.Context, tokenID Hash256) (*RefreshTokenSession, error)
- func (s *TieredStorage) RefreshTokenRevoke(ctx context.Context, tokenID Hash256) error
- func (s *TieredStorage) RefreshTokenRevokeUser(ctx context.Context, userID BinaryUUID) ([]Hash256, error)
- func (s *TieredStorage) RefreshTokenRotate(ctx context.Context, oldTokenID Hash256, newSession *RefreshTokenSession, ...) error
- type TokenCache
- type TokenRequest
- type TokenStorage
- type TokenVerifier
- type UserAuthenticator
- type UserInfo
- type UserInfoGetter
Constants ¶
const ( DeviceCodeStatusPending = "pending" DeviceCodeStatusAllowed = "allowed" DeviceCodeStatusDenied = "denied" )
const ( // Response Types ResponseTypeCode = "code" // Grant Types GrantTypeAuthorizationCode = "authorization_code" GrantTypeRefreshToken = "refresh_token" GrantTypeClientCredentials = "client_credentials" GrantTypePassword = "password" GrantTypeDeviceCode = "urn:ietf:params:oauth:grant-type:device_code" // Subject Types SubjectTypePublic = "public" // Auth Methods AuthMethodClientSecretBasic = "client_secret_basic" AuthMethodClientSecretPost = "client_secret_post" // Scopes ScopeOpenID = "openid" ScopeProfile = "profile" ScopeEmail = "email" ScopePhone = "phone" ScopeOfflineAccess = "offline_access" )
const ( // CodeChallengeMethodS256 是推荐的 PKCE 转换方法 CodeChallengeMethodS256 = "S256" // CodeChallengeMethodPlain 是不推荐的方法,仅用于兼容性 CodeChallengeMethodPlain = "plain" )
const ( // DefaultKeyCacheTTL 是本地缓存签名 Key ID 的默认有效期 // 在分布式环境中,这决定了轮换后其他实例感知到的最大延迟 DefaultKeyCacheTTL = 30 * time.Second )
Variables ¶
var ( // ErrInvalidRequest 请求缺少必需的参数、包含无效的参数值、包含多个同名参数,或者格式不正确。 ErrInvalidRequest = errors.New("invalid_request") // ErrInvalidClient 客户端认证失败(例如:未知的客户端、未包含客户端认证信息、不支持的认证方法)。 ErrInvalidClient = errors.New("invalid_client") // ErrInvalidGrant 提供的授权许可(例如:授权码、资源所有者凭据)或刷新令牌无效、过期、已撤销、与重定向 URI 不匹配,或不属于该客户端。 ErrInvalidGrant = errors.New("invalid_grant") ErrUnauthorizedClient = errors.New("unauthorized_client") // ErrUnsupportedGrantType 授权服务器不支持该授权许可类型。 ErrUnsupportedGrantType = errors.New("unsupported_grant_type") // ErrInvalidScope 请求的范围无效、未知、格式不正确,或超出了资源所有者授予的范围。 ErrInvalidScope = errors.New("invalid_scope") // ErrAccessDenied 资源所有者或授权服务器拒绝了请求。 ErrAccessDenied = errors.New("access_denied") // ErrServerError 授权服务器遇到意外情况,无法完成请求。 ErrServerError = errors.New("server_error") ErrTemporarilyUnavailable = errors.New("temporarily_unavailable") )
var ( // ErrAuthorizationPending 设备授权请求待处理,客户端应继续轮询。 ErrAuthorizationPending = errors.New("authorization_pending") // ErrSlowDown 客户端轮询过于频繁,应减慢轮询速率。 ErrSlowDown = errors.New("slow_down") // ErrExpiredToken 设备码已过期。 ErrExpiredToken = errors.New("expired_token") )
var ( ErrTokenExpired = errors.New("token is expired") ErrTokenSignatureInvalid = errors.New("token signature is invalid") ErrInvalidIssuer = errors.New("invalid issuer") ErrInvalidAudience = errors.New("invalid audience") ErrInvalidNonce = errors.New("invalid nonce") ErrNotFound = errors.New("resource not found") ErrTokenFormatInvalid = errors.New("token format is invalid") ErrTokenForged = errors.New("token forged") )
var ( ErrClientNotFound = errors.New("client not found") ErrTokenNotFound = errors.New("token not found or expired") ErrCodeNotFound = errors.New("authorization code not found or consumed") ErrUserNotFound = errors.New("user not found") )
var ( // ErrKeyNil 密钥不能为 nil ErrKeyNil = errors.New("key cannot be nil") // ErrInvalidRSAKey 无效的 RSA 私钥 ErrInvalidRSAKey = errors.New("invalid RSA private key") // ErrRSAKeyTooSmall RSA 私钥必须至少 2048 位 ErrRSAKeyTooSmall = errors.New("RSA private key must be at least 2048 bits") // ErrInvalidEd25519KeySize 无效的 Ed25519 私钥大小 ErrInvalidEd25519KeySize = errors.New("invalid Ed25519 private key size") // ErrNoSigningKey 未配置签名密钥 ErrNoSigningKey = errors.New("no signing key configured") // ErrKeyNotFound 密钥未找到 ErrKeyNotFound = errors.New("key not found") // ErrTokenRevoked 表示 Access Token 已被撤销 (例如用户登出或安全事件) ErrTokenRevoked = errors.New("token has been revoked") // ErrCannotRemoveSigningKey 不能删除当前的签名密钥 ErrCannotRemoveSigningKey = errors.New("cannot remove current signing key") // ErrUnsupportedKeyType 不支持的密钥类型 ErrUnsupportedKeyType = errors.New("unsupported key type") // ErrCircuitBreakerOpen 断路器打开 ErrCircuitBreakerOpen = errors.New("remote JWKS unavailable (circuit breaker open)") // ErrKeyExpired 密钥已过期 ErrKeyExpired = errors.New("key expired") // ErrNoActiveKey 未设置活跃密钥 ErrNoActiveKey = errors.New("no active key set") // ErrKIDEmpty KID 不能为空 ErrKIDEmpty = errors.New("kid cannot be empty") // ErrKeyTooShort 密钥长度不足 ErrKeyTooShort = errors.New("key must be at least 32 bytes") // ErrCannotRemoveActiveKey 不能删除活跃密钥 ErrCannotRemoveActiveKey = errors.New("cannot remove active key") // ErrUnsupportedECDSACurve 不支持的 ECDSA 曲线 ErrUnsupportedECDSACurve = errors.New("unsupported ECDSA curve") // ErrUnsupportedPrivateKeyType 不支持的私钥类型 ErrUnsupportedPrivateKeyType = errors.New("unsupported private key type") // ErrSigningKeyMissing 当前签名密钥丢失 ErrSigningKeyMissing = errors.New("current signing key is missing") // ErrKeyInterfaceNotImplemented 存储的密钥未实现 Key 接口 ErrKeyInterfaceNotImplemented = errors.New("stored key does not implement Key interface") // ErrNoActiveRefreshTokenKey 没有用于刷新令牌的活跃密钥 ErrNoActiveRefreshTokenKey = errors.New("hmac key check failed: no active key for refresh tokens") // ErrSchedulerAlreadyStarted 调度器已启动 ErrSchedulerAlreadyStarted = errors.New("scheduler already started") // ErrRotationInProgress 另一个实例正在进行轮换 ErrRotationInProgress = errors.New("rotation already in progress by another instance") // ErrMemoryProviderOnly 操作仅支持 MemoryKeyProvider ErrMemoryProviderOnly = errors.New("operation only supported for MemoryKeyProvider") )
var ( // ErrPKCEVerifierEmpty PKCE verifier 不能为空 ErrPKCEVerifierEmpty = errors.New("pkce verifier cannot be empty") // ErrPKCEVerifierInvalidLength PKCE verifier 长度无效 ErrPKCEVerifierInvalidLength = errors.New("invalid pkce verifier length") // ErrPKCEVerifierInvalidChars PKCE verifier 包含无效字符 ErrPKCEVerifierInvalidChars = errors.New("invalid characters in pkce verifier") // ErrPKCEVerificationFailed PKCE 验证失败 ErrPKCEVerificationFailed = errors.New("pkce verification failed") // ErrPKCERandomnessGenerationFailed PKCE 随机数生成失败 ErrPKCERandomnessGenerationFailed = errors.New("failed to generate randomness for pkce") // ErrUnsupportedPKCEChallengeMethod 不支持的 PKCE challenge 方法 ErrUnsupportedPKCEChallengeMethod = errors.New("unsupported pkce challenge method") )
var ( // ErrKeyNotEC 密钥不是 EC 类型 ErrKeyNotEC = errors.New("key is not EC") // ErrKeyNotRSA 密钥不是 RSA 类型 ErrKeyNotRSA = errors.New("key is not RSA") // ErrKeyNotEd25519 密钥不是 Ed25519 类型 ErrKeyNotEd25519 = errors.New("key is not Ed25519") // ErrInvalidEd25519PublicKeySize 无效的 Ed25519 公钥大小 ErrInvalidEd25519PublicKeySize = errors.New("invalid Ed25519 public key size") // ErrInvalidJWKType 无效的 JWK 类型 ErrInvalidJWKType = errors.New("invalid JWK type") // ErrMissingJWKFields 缺少 JWK 字段 ErrMissingJWKFields = errors.New("missing JWK fields") // ErrUnsupportedJWKPublicKeyType 不支持的 JWK 公钥类型 ErrUnsupportedJWKPublicKeyType = errors.New("jwks: unsupported key type") // ErrUnsupportedKtyForThumbprint 不支持的 kty 用于指纹计算 ErrUnsupportedKtyForThumbprint = errors.New("unsupported kty for thumbprint") // ErrUnsupportedCurve 不支持的曲线 ErrUnsupportedCurve = errors.New("jwks: unsupported curve") )
var ( // ErrIssuerEmpty 发行者不能为空 ErrIssuerEmpty = errors.New("issuer cannot be empty") // ErrInvalidIssuerURL 发行者必须是有效的 URL ErrInvalidIssuerURL = errors.New("issuer must be a valid URL") // ErrInvalidTTL Token TTL 必须大于 0 ErrInvalidTTL = errors.New("token TTL must be greater than 0") // ErrKeyManagerNil KeyManager 不能为 nil ErrKeyManagerNil = errors.New("keyManager cannot be nil") // ErrSecretManagerNil SecretManager 不能为 nil ErrSecretManagerNil = errors.New("secretManager cannot be nil") // ErrFailedToGenerateUUID 生成 UUID 失败 ErrFailedToGenerateUUID = errors.New("failed to generate UUIDv7") // ErrUnsupportedSigningKeyType 不支持的签名密钥类型 ErrUnsupportedSigningKeyType = errors.New("unsupported signing key type") // ErrUnsupportedAlgForHash 不支持的哈希计算算法 ErrUnsupportedAlgForHash = errors.New("unsupported alg for hash calculation") )
var ( // ErrHash256InvalidLength Hash256 必须为 32 字节 ErrHash256InvalidLength = errors.New("Hash256 must be exactly 32 bytes") // ErrHash256ScanInvalidLength 扫描失败: Hash256 应为 32 字节 ErrHash256ScanInvalidLength = errors.New("scan failed: expected 32 bytes for Hash256") // ErrHash256UnsupportedType 扫描失败: Hash256 不支持的类型 ErrHash256UnsupportedType = errors.New("scan failed: unsupported type for Hash256") // ErrInvalidHexStringLength 无效的十六进制字符串长度 ErrInvalidHexStringLength = errors.New("invalid hex string length") // ErrBinaryUUIDUnsupportedType BinaryUUID 无法扫描的类型 ErrBinaryUUIDUnsupportedType = errors.New("BinaryUUID: cannot scan type") )
var ( // ErrUserIDRequired 生成授权码需要 user_id ErrUserIDRequired = errors.New("user_id is required to generate authorization code") // ErrTokenIsInvalid Token 无效 ErrTokenIsInvalid = errors.New("token is invalid") // ErrExpClaimRequired exp 声明是必需的 ErrExpClaimRequired = errors.New("exp claim is required") // ErrAZPRequired 当存在多个受众时需要 azp 声明 ErrAZPRequired = errors.New("azp claim is required when multiple audiences are present") // ErrAZPMismatch azp 与 client_id 不匹配 ErrAZPMismatch = errors.New("azp does not match client_id") // ErrAZPRequiredForTrust 受信任的客户端验证需要 azp 声明 ErrAZPRequiredForTrust = errors.New("azp claim is required for trusted client validation") // ErrAZPNotAuthorized azp 未被授权访问资源 ErrAZPNotAuthorized = errors.New("azp is not authorized to access resource") // ErrUnexpectedSigningMethod 意外的签名方法 ErrUnexpectedSigningMethod = errors.New("unexpected signing method") // ErrHasherNotConfigured Hasher 未配置 ErrHasherNotConfigured = errors.New("hasher not configured") // ErrInvalidIdentifier 无效的标识符 ErrInvalidIdentifier = errors.New("invalid identifier") // ErrUserNotConfirmed 用户未确认 ErrUserNotConfirmed = errors.New("user not confirmed") // ErrUserForbidden 用户被禁用 ErrUserForbidden = errors.New("user forbidden") // ErrDefaultPassword 使用默认密码 ErrDefaultPassword = errors.New("default password") // ErrIssuerURLRequired issuer URL 是必需的 ErrIssuerURLRequired = errors.New("issuer url is required") // ErrStorageRequired storage 实现是必需的 ErrStorageRequired = errors.New("storage implementation is required") // ErrHasherRequired hasher 实现是必需的 ErrHasherRequired = errors.New("hasher implementation is required") // ErrSecretHasherRequired 机密客户端需要 secret hasher ErrSecretHasherRequired = errors.New("secret hasher is required for confidential clients") // ErrEnvTokenSecretRequired 环境变量 OIDC_TOKEN_SECRET 是必需的 ErrEnvTokenSecretRequired = errors.New("env OIDC_TOKEN_SECRET is required") )
var ( // ErrPARNotSupported 服务器不支持 PAR ErrPARNotSupported = errors.New("server does not support PAR") // ErrDeviceFlowNotSupported 服务器不支持设备流 ErrDeviceFlowNotSupported = errors.New("server does not support device flow") // ErrRevocationNotSupported 服务器不支持撤销 ErrRevocationNotSupported = errors.New("server does not support revocation") // ErrIntrospectionNotSupported 服务器不支持内省 ErrIntrospectionNotSupported = errors.New("server does not support introspection") // ErrNonceMismatch nonce 不匹配 ErrNonceMismatch = errors.New("nonce mismatch") // ErrUnparseableError 请求失败且错误无法解析 ErrUnparseableError = errors.New("request failed with unparseable error") )
var AllowedSchemes = map[string]struct{}{
"http": {},
"https": {},
}
var DefaultSupportedSigningAlgs = []string{"RS256", "RS384", "RS512", "ES256", "ES384", "ES512", "EdDSA"}
DefaultSupportedSigningAlgs 默认支持的签名算法
var ErrInvalidURNFormat = errors.New("invalid urn format")
ErrInvalidURNFormat 无效的 URN 格式
Functions ¶
func BuildDPoPBoundAccessTokenURI ¶
BuildDPoPBoundAccessTokenURI 构建资源请求 URI (去除查询参数和片段) RFC 9449 要求 htu 与实际请求的 URI 匹配(不含查询参数)
func BuildRedirectURL ¶
BuildRedirectURL 拼接 URL 参数
func BuildRequestURI ¶
BuildRequestURI 构建 HTTP 请求的完整 URI (不含 query 和 fragment) RFC 9449 Section 4.2: htu 必须是 scheme + host + path,不包含 query 和 fragment
func ComputeJKT ¶
ComputeJKT 计算 JWK Thumbprint (RFC 7638) 用于生成 cnf.jkt claim
func ComputePKCEChallenge ¶
ComputePKCEChallenge 根据给定的 Verifier 和 Method 计算 Challenge。 目前主要支持 S256。
func DPoPMiddleware ¶
DPoPMiddleware 创建一个中间件来验证 DPoP proof 如果验证成功,将 DPoPClaims 存入 context 如果验证失败,返回 401 错误
使用方式:
middleware := oidc.DPoPMiddleware(server, replayCache, true) handler := middleware(yourHandler)
func DPoPOptionalMiddleware ¶
func DPoPOptionalMiddleware(cache ReplayCache) func(http.Handler) http.Handler
DPoPOptionalMiddleware 创建一个可选的 DPoP 中间件 如果提供了 DPoP header 则验证,否则继续处理
func DPoPProtectedEndpoints ¶
func DPoPProtectedEndpoints() []string
DPoPProtectedEndpoints 返回需要 DPoP 保护的端点列表 通常包括:/token, /userinfo, /introspect
func DPoPRequiredMiddleware ¶
func DPoPRequiredMiddleware(cache ReplayCache) func(http.Handler) http.Handler
DPoPRequiredMiddleware 创建一个必需的 DPoP 中间件 如果未提供 DPoP header 则返回 401 错误
func DecodeJSON ¶
DecodeJSON 是一个安全的 JSON 解码辅助函数。 它启用 UseNumber() 选项,防止大整数(如 expires_in 或 ID)被错误解析为 float64 导致精度丢失。
func DeviceAuthorized ¶
func DeviceAuthorized(ctx context.Context, storage Storage, req *DeviceAuthorizedRequest) error
DeviceAuthorized 处理设备授权确认 (用户在前端点击同意后调用)
func DeviceDenied ¶
补充:处理用户拒绝授权的逻辑 (建议添加)
func EndSession ¶
func EndSession(ctx context.Context, storage Storage, verifier TokenVerifier, req *EndSessionRequest) (string, error)
EndSession 处理用户登出请求
func ExtractDPoPJKT ¶
ExtractDPoPJKT 是一个辅助函数,用于从 context 中提取 JKT 如果不存在则返回空字符串
func GeneratePKCEVerifier ¶
GeneratePKCEVerifier 生成一个符合 RFC 7636 标准的高熵随机字符串。 长度默认为 43 字符(32 字节熵)。
func GetSigningMethod ¶
func GetSigningMethod(key crypto.PrivateKey) jwt.SigningMethod
GetSigningMethod 根据私钥类型返回对应的 JWT 签名方法
func Hash ¶
func Hash(method jwt.SigningMethod, str string) (string, error)
Hash 根据签名算法计算字符串的哈希值 OIDC 规范:使用 ID 令牌头部指定的哈希算法对令牌 ASCII 表示的字节进行哈希处理。取哈希值的左半部分并进行 base64url 编码。
func IsConfidentialClient ¶ added in v0.3.9
IsConfidentialClient 判断客户端类型
func ParseECDSAPublicKeyFromJWK ¶
func ParseECDSAPublicKeyFromJWK(jwk *JSONWebKey) (*ecdsa.PublicKey, error)
ParseECDSAPublicKeyFromJWK 是一个辅助函数,用于将 JWK 转换回 *ecdsa.PublicKey (主要用于 Client 端验证)。
func ParseEd25519PublicKeyFromJWK ¶
func ParseEd25519PublicKeyFromJWK(jwk *JSONWebKey) (ed25519.PublicKey, error)
ParseEd25519PublicKeyFromJWK 解析 Ed25519 JWK
func ParseRSAPublicKeyFromJWK ¶
func ParseRSAPublicKeyFromJWK(jwk *JSONWebKey) (*rsa.PublicKey, error)
ParseRSAPublicKeyFromJWK 是一个辅助函数,用于将 JWK 转换回 *rsa.PublicKey。
func RandomString ¶
RandomString 生成指定长度的随机字符串 (URL Safe Base64)
func RefreshTokenRevoke ¶ added in v0.3.0
func RefreshTokenRevoke(ctx context.Context, storage TokenStorage, secretManager *SecretManager, tokenStr string, client RegisteredClient) error
RefreshTokenRevoke 处理 Opaque Refresh Token 的撤销 (物理删除/标记)
func RegisterMetrics ¶
func RegisterMetrics()
RegisterMetrics 注册 OIDC 相关的 metrics 到 o11y registry 这个函数应该在初始化 OIDC Server 之后,启动服务之前调用 通常在 main.go 中调用一次即可
示例用法:
shutdown := o11y.Init(cfg.O11y) defer shutdown(context.Background()) oidc.RegisterMetrics() // 注册 OIDC 指标
func ResponseAuthorized ¶
func ResponseAuthorized(ctx context.Context, storage AuthCodeStorage, req *AuthorizeRequest, codeTTL time.Duration) (string, error)
ResponseAuthorized 在用户通过身份验证并同意授权后调用。 它生成 Authorization Code,保存到存储层,并返回包含 code 和 state 的重定向 URL。
func RevokeAccessToken ¶
func RevokeAccessToken(ctx context.Context, storage RevocationStorage, verifier TokenVerifier, tokenStr string, client RegisteredClient) error
RevokeAccessToken 处理 JWT Access Token 的撤销 (加入黑名单)
func RevokeToken ¶
func RevokeToken(ctx context.Context, storage Storage, secretManager *SecretManager, hasher Hasher, verifier TokenVerifier, req *RevocationRequest) error
RevokeToken 是一个无状态函数,直接由 Server 调用
func SetServerTimeHeader ¶
func SetServerTimeHeader(w http.ResponseWriter)
SetServerTimeHeader 设置服务器时间响应头 帮助客户端计算时间偏差
func UnregisterClient ¶
func UnregisterClient(ctx context.Context, storage ClientStorage, clientIDStr string) error
UnregisterClient 注销客户端 注意:实际业务中通常需要验证是否有权删除(如验证 Registration Access Token 或 OwnerID)
func ValidateRegistrationRequest ¶
func ValidateRegistrationRequest(req *ClientRegistrationRequest, allowedSchemes map[string]struct{}) error
ValidateRegistrationRequest 集中处理校验逻辑
func ValidateScopes ¶
ValidateScopes 检查 requestedScope 是否是 allowedScope 的子集 支持通配符匹配: - "scope:*" 匹配 "scope:read", "scope:write" - "scope:read:*" 匹配 "scope:read:user" - "*" 匹配所有
func ValidateStructuredRefreshToken ¶
func ValidateStructuredRefreshToken(ctx context.Context, sm *SecretManager, token RefreshToken) error
验证 Token (在查库之前)
func VerifyDPoPProof ¶
func VerifyDPoPProof( ctx context.Context, req *http.Request, w http.ResponseWriter, cache ReplayCache, httpMethod, httpURI string, ) (jkt string, err error)
VerifyDPoPProof 验证 HTTP 请求中的 DPoP Proof 返回 JWK Thumbprint (jkt) 用于绑定到 Access Token
RFC 9449 验证步骤: 1. 解析 DPoP header 中的 JWT 2. 验证 JWT 签名 (公钥在 header 的 jwk 字段) 3. 验证 htm 和 htu 与请求匹配 4. 验证 iat 时间窗口 (推荐 ±60秒) 5. 验证 jti 防重放 (使用 ReplayCache) 6. 计算并返回 JKT (JWK Thumbprint)
w: 可选的 ResponseWriter,用于在验证失败时设置服务器时间响应头
func VerifyPKCE ¶
VerifyPKCE 验证前端传来的 Verifier 是否与存储的 Challenge 匹配。
Types ¶
type AccessToken ¶
type AccessToken SecretString
func (AccessToken) Hash ¶
func (ac AccessToken) Hash(alg jwt.SigningMethod) (string, error)
Hash 根据签名算法计算 Access Token 的哈希值 规范要求:Hash 算法必须匹配 ID Token 的签名算法
type AccessTokenClaims ¶
type AccessTokenClaims struct {
jwt.RegisteredClaims
// --- OAuth2 协议核心字段 ---
Scope string `json:"scope,omitempty"` // 核心权限字段!例如 "read:orders write:profile"
// --- 扩展字段 ---
AuthorizedParty string `json:"azp,omitempty"` // 哪个 Client 发起的请求?(用于限流、审计)
// --- DPoP (RFC 9449) ---
// Confirmation claim: 用于 DPoP sender-constrained tokens
// 格式: {"jkt": "<JWK Thumbprint>"}
Confirmation map[string]interface{} `json:"cnf,omitempty"`
}
AccessTokenClaims 表示自定义的 Access Token 载荷。 虽然 OAuth2 没有严格规定 Access Token 格式,但使用 JWT 是常见做法。
func (*AccessTokenClaims) SignedString ¶
func (ac *AccessTokenClaims) SignedString(method jwt.SigningMethod, privateKey crypto.PrivateKey) (AccessToken, error)
type AuthCodeSession ¶
type AuthCodeSession struct {
// Code: 授权码本身作为主键,必须是唯一的
Code string `db:"code"`
// 关联索引:Token Exchange 时需验证 ClientID,且包含 UserID
ClientID BinaryUUID `db:"client_id"`
UserID BinaryUUID `db:"user_id"`
AuthTime time.Time
// ExpiresAt: 必须加索引,用于定期清理过期数据 (GC)
ExpiresAt time.Time `db:"expires_at"`
// ACR/AMR: 认证上下文 (可选)
ACR string `db:"acr"`
AMR []string `db:"amr"`
// 原始请求参数校验
RedirectURI string `db:"redirect_uri"`
Scope string `db:"scope"`
Nonce string `db:"nonce"`
// PKCE (RFC 7636): 必须字段
CodeChallenge string `db:"code_challenge"`
CodeChallengeMethod string `db:"code_challenge_method"`
// DPoP JKT (RFC 9449): 绑定指纹,防止 Code 窃取
DPoPJKT string `db:"d_pop_jkt"`
}
AuthCodeSession 授权码会话 (临时数据), 这些信息需要在 Exchange 阶段被恢复。 存活时间极短 (通常 < 10分钟),读写极高
func (AuthCodeSession) TableName ¶ added in v0.3.0
func (AuthCodeSession) TableName() string
type AuthCodeStorage ¶
type AuthCodeStorage interface {
// AuthCodeSave 存储生成的授权码及其上下文。
AuthCodeSave(ctx context.Context, session *AuthCodeSession) error
// AuthCodeConsume 查找并标记为已使用(防止重放)。
// 这是一个原子操作:读取的同时必须确保下次读取失败或标记为已消耗。
// 如果未找到或已过期/已消耗,应返回 ErrCodeNotFound。
AuthCodeConsume(ctx context.Context, code string) (*AuthCodeSession, error)
}
type AuthorizeRequest ¶
type AuthorizeRequest struct {
// 必需参数
ClientID string `form:"client_id" json:"client_id"`
RedirectURI string `form:"redirect_uri" json:"redirect_uri"`
ResponseType string `form:"response_type" json:"response_type"` // 目前仅支持 "code"
// 可选参数
Scope string `form:"scope" json:"scope"`
State string `form:"state" json:"state"`
Nonce string `form:"nonce" json:"nonce"`
CodeChallenge string `form:"code_challenge" json:"code_challenge"`
CodeChallengeMethod string `form:"code_challenge_method" json:"code_challenge_method"`
// PAR (RFC 9126): 推送授权请求 URI
// 如果存在,忽略其他参数,从 PARStorage 加载完整请求
RequestURI string `form:"request_uri" json:"request_uri"`
// DPoP (RFC 9449): JWK Thumbprint from DPoP proof
// 由 HTTP Handler 验证 DPoP Proof 后提取并传入
// 将被绑定到 Auth Code,在 Token Exchange 时验证
DPoPJKT string `form:"-" json:"-"`
// 上下文数据 (由调用者在用户登录/确认后填充)
UserID string `form:"-" json:"-"`
AuthTime time.Time `form:"-" json:"-"`
// FinalScope 允许调用者在业务层修改最终授予的 Scope (例如移除用户无权的 scope)
// 如果为空,将默认使用请求的 Scope
FinalScope string `form:"-" json:"-"`
}
AuthorizeRequest 封装授权端点的请求参数
func LoadPARSession ¶
func LoadPARSession(ctx context.Context, storage PARStorage, requestURI string) (*AuthorizeRequest, error)
LoadPARSession 从 request_uri 加载授权请求参数 仅在 /authorize 端点内部使用
type BinaryUUID ¶
BinaryUUID 包装标准 UUID,强制数据库交互使用二进制
func NewBinaryUUID ¶ added in v0.3.0
func NewBinaryUUID() (BinaryUUID, error)
NewBinaryUUID 创建一个 uuid v7
func (BinaryUUID) MarshalJSON ¶
func (b BinaryUUID) MarshalJSON() ([]byte, error)
MarshalJSON 必须重写!否则 Go 会把底层 []byte 转成 Base64 字符串
func (*BinaryUUID) Scan ¶
func (b *BinaryUUID) Scan(value interface{}) error
Scan 实现 sql.Scanner (从数据库读取)
func (*BinaryUUID) UnmarshalJSON ¶
func (b *BinaryUUID) UnmarshalJSON(data []byte) error
UnmarshalJSON 从字符串解析
type Cache ¶
type Cache interface {
AuthCodeStorage // 极短 TTL
DeviceCodeStorage // 短 TTL
DistributedLock // 分布式锁
PARStorage // 极短 TTL
ReplayCache // DPoP JTI 防重放
RevocationStorage // Access Token 黑名单 (高频读取)
// 用于多级缓存, “缓存穿透”和“回写”的逻辑
KeyStorage // JWK (基础设施)
ClientCache
TokenCache
}
Cache 负责临时、高频、需要自动过期的数据 建议实现:Redis
type ClientCache ¶
type ClientCache interface {
// ClientGetByID 从缓存获取客户端
ClientGetByID(ctx context.Context, clientID BinaryUUID) (RegisteredClient, error)
// ClientSave 将客户端存入缓存
ClientSave(ctx context.Context, client RegisteredClient, ttl time.Duration) error
// ClientInvalidate 从缓存中移除客户端
ClientInvalidate(ctx context.Context, clientID BinaryUUID) error
}
ClientCache 定义了客户端信息的缓存接口。
type ClientFactory ¶
type ClientFactory interface {
New() RegisteredClient
}
ClientFactory 定义了创建客户端的接口。
type ClientMetadata ¶
type ClientMetadata struct {
// ID: 主键,使用 UUID
ID BinaryUUID `db:"id"`
// OwnerID: 用于查询“我创建的应用”,需要索引
OwnerID BinaryUUID `db:"owner_id"`
// Secret: 客户端密钥,经过哈希,预留足够长度
Secret SecretString `db:"secret"`
// Name: 应用名称
Name string `db:"name"`
// 数组类型处理:
RedirectURIs StringSlice `db:"redirect_uris"`
GrantTypes StringSlice `db:"grant_types"`
// Scope: 空格分隔的字符串,或者也可以用 type:text
Scope string `db:"scope"`
LogoURI string `db:"logo_uri"`
TokenEndpointAuthMethod string `db:"token_endpoint_auth_method"`
// IsConfidentialClient: 区分公开/机密客户端
IsConfidentialClient bool `db:"is_confidential_client"`
CreatedAt time.Time `db:"created_at"`
UpdatedAt time.Time `db:"updated_at"`
}
ClientMetadata 客户端注册信息 对应 OAuth 2.0 Dynamic Client Registration Protocol
func (*ClientMetadata) Deserialize ¶ added in v0.3.0
func (c *ClientMetadata) Deserialize(data string) error
func (*ClientMetadata) GetGrantTypes ¶ added in v0.3.0
func (c *ClientMetadata) GetGrantTypes() []string
func (*ClientMetadata) GetID ¶ added in v0.3.0
func (c *ClientMetadata) GetID() BinaryUUID
func (*ClientMetadata) GetRedirectURIs ¶ added in v0.3.0
func (c *ClientMetadata) GetRedirectURIs() []string
func (*ClientMetadata) GetScope ¶ added in v0.3.0
func (c *ClientMetadata) GetScope() string
func (*ClientMetadata) IsConfidential ¶
func (c *ClientMetadata) IsConfidential() bool
func (*ClientMetadata) Metadata ¶ added in v0.3.2
func (c *ClientMetadata) Metadata() *ClientMetadata
func (*ClientMetadata) Serialize ¶ added in v0.3.0
func (c *ClientMetadata) Serialize() (string, error)
func (ClientMetadata) TableName ¶ added in v0.3.0
func (ClientMetadata) TableName() string
func (*ClientMetadata) ValidateSecret ¶ added in v0.3.0
ValidateSecret 需要 hasher 协助,这里只提供数据,逻辑在 Server 层或 Storage 方法中 为了满足接口,我们在 Storage 实现中处理,这里仅作占位
type ClientRegistrationRequest ¶
type ClientRegistrationRequest struct {
RedirectURIs []string `json:"redirect_uris"`
GrantTypes []string `json:"grant_types"`
ResponseTypes []string `json:"response_types"`
Scope string `json:"scope"`
ClientName string `json:"client_name"`
LogoURI string `json:"logo_uri,omitempty"`
ClientURI string `json:"client_uri,omitempty"`
// auth_method 决定了是否需要生成 secret
// options: client_secret_basic, client_secret_post, none, private_key_jwt
TokenEndpointAuthMethod string `json:"token_endpoint_auth_method"`
// 扩展字段:绑定所有者
OwnerID string `json:"-"`
}
ClientRegistrationRequest RFC 7591 Client Registration Request
type ClientRegistrationResponse ¶
type ClientRegistrationResponse struct {
ClientID string `json:"client_id"`
ClientSecret string `json:"client_secret,omitempty"` // 仅在创建或重置时返回明文
ClientSecretExpiresAt int64 `json:"client_secret_expires_at,omitempty"`
RedirectURIs []string `json:"redirect_uris"`
GrantTypes []string `json:"grant_types"`
Scope string `json:"scope"`
ClientName string `json:"client_name"`
LogoURI string `json:"logo_uri,omitempty"`
TokenEndpointAuthMethod string `json:"token_endpoint_auth_method"`
RegistrationAccessToken string `json:"registration_access_token,omitempty"`
RegistrationClientURI string `json:"registration_client_uri,omitempty"`
}
ClientRegistrationResponse RFC 7591 Response
func ClientUpdate ¶ added in v0.3.0
func ClientUpdate(ctx context.Context, storage ClientStorage, req *ClientUpdateRequest) (*ClientRegistrationResponse, error)
ClientUpdate 更新客户端信息 RFC 7592: Update Request
func RegisterClient ¶
func RegisterClient(ctx context.Context, storage ClientStorage, hasher Hasher, req *ClientRegistrationRequest) (*ClientRegistrationResponse, error)
RegisterClient 处理新客户端注册 hasher: 必填,用于对生成的 Secret 进行哈希处理后再存入 DB
type ClientStorage ¶
type ClientStorage interface {
// ClientGetByID 根据 ID 获取客户端详情。
// 如果未找到,应返回 ErrClientNotFound。
ClientGetByID(ctx context.Context, clientID BinaryUUID) (RegisteredClient, error)
// ClientCreate 注册新客户端
// 注意:metadata.Secret 必须已经通过 Hasher.Hash() 哈希处理
ClientCreate(ctx context.Context, metadata *ClientMetadata) (RegisteredClient, error)
// ClientUpdate 更新客户端元数据
ClientUpdate(ctx context.Context, metadata *ClientMetadata) (RegisteredClient, error)
// ClientDeleteByID 删除客户端
ClientDeleteByID(ctx context.Context, clientID BinaryUUID) error
// ClientListByOwner 根据所有者查询客户端 (可选)
ClientListByOwner(ctx context.Context, ownerID BinaryUUID, query ListQuery) ([]RegisteredClient, error)
// ClientListAll 列出所有客户端
ClientListAll(ctx context.Context, query ListQuery) ([]RegisteredClient, error)
}
ClientStorage 定义了获取客户端信息的接口。
type ClientUpdateRequest ¶
type ClientUpdateRequest struct {
ClientID string `json:"client_id"`
*ClientRegistrationRequest
}
ClientUpdateRequest RFC 7591 Client Update Request
type ClientVerifier ¶
type ClientVerifier struct {
// contains filtered or unexported fields
}
ClientVerifier 用于客户端验证 OIDC ID Token。
func NewClientVerifier ¶
func NewClientVerifier(issuer, clientID string, keySet KeySource) *ClientVerifier
NewClientVerifier 创建一个新的客户端验证器。 issuer: 必须完全匹配 Token 中的 iss。 clientID: 必须包含在 Token 的 aud 中。
func (*ClientVerifier) SetSupportedSigningAlgs ¶
func (v *ClientVerifier) SetSupportedSigningAlgs(algs []string)
SetSupportedSigningAlgs 设置支持的签名算法
func (*ClientVerifier) Verify ¶
func (v *ClientVerifier) Verify(ctx context.Context, rawToken string) (*IDTokenClaims, error)
Verify 解析并验证原始 ID Token 字符串。
type Code ¶
type Code SecretString
type DPoPClaims ¶
type DPoPClaims struct {
JKT string // JWK Thumbprint,用于绑定到 Access Token
}
DPoPClaims 存储 DPoP 验证后的信息
func DPoPFromContext ¶
func DPoPFromContext(ctx context.Context) (*DPoPClaims, bool)
DPoPFromContext 从 context 中提取 DPoP 验证结果 返回 (claims, ok),如果 ok == false 表示未使用 DPoP
type DPoPProof ¶
type DPoPProof struct {
jwt.RegisteredClaims
// htm: HTTP 方法 (必需)
HTM string `json:"htm"`
// htu: HTTP URI (必需,不包含查询参数和片段)
HTU string `json:"htu"`
// Nonce: 可选,服务器可以要求客户端包含 nonce 以防重放
Nonce string `json:"nonce,omitempty"`
}
DPoPProof 表示 DPoP Proof JWT 的 Claims RFC 9449 Section 4.2
type DPoPTimeSkewError ¶
type DPoPTimeSkewError struct {
Info DPoPTimeSkewInfo
Err error
}
DPoPTimeSkewError DPoP 时间偏差错误 包含详细的时间信息以便客户端调试
func (*DPoPTimeSkewError) Error ¶
func (e *DPoPTimeSkewError) Error() string
func (*DPoPTimeSkewError) Unwrap ¶
func (e *DPoPTimeSkewError) Unwrap() error
type DPoPTimeSkewInfo ¶
DPoPTimeSkewInfo 记录 DPoP 时间偏差信息
type DeviceAuthorizationResponse ¶
type DeviceAuthorizationResponse struct {
DeviceCode string `json:"device_code"`
UserCode string `json:"user_code"`
VerificationURI string `json:"verification_uri"`
ExpiresIn int `json:"expires_in"`
Interval int `json:"interval,omitempty"` // Polling interval in seconds
}
func DeviceAuthorization ¶
func DeviceAuthorization(ctx context.Context, storage Storage, issuer string, req *DeviceAuthorizationRequest) (*DeviceAuthorizationResponse, error)
DeviceAuthorization 处理设备授权请求
type DeviceAuthorizedRequest ¶
type DeviceCodeSession ¶
type DeviceCodeSession struct {
// DeviceCode: 设备换取 Token 的凭证,主键
DeviceCode string `db:"device_code"`
// UserCode: 用户在浏览器输入的短码,必须唯一且有索引
UserCode string `db:"user_code"`
ClientID BinaryUUID `db:"client_id"`
UserID BinaryUUID `db:"user_id"` // 初始为空,用户授权后填充
Scope string `db:"scope"`
ExpiresAt time.Time `db:"expires_at"` // 用于清理
LastPolled time.Time // 用于频率限制 (Rate Limiting)检查
// Status: pending, allowed, denied
Status string `db:"status"`
AuthTime time.Time
AuthorizedScope string `db:"authorized_scope"` // 用户实际同意的 Scope
}
DeviceCodeSession 设备流会话 (RFC 8628)
func (DeviceCodeSession) TableName ¶ added in v0.3.0
func (DeviceCodeSession) TableName() string
type DeviceCodeStorage ¶
type DeviceCodeStorage interface {
// DeviceCodeSave 存储设备码和用户码
DeviceCodeSave(ctx context.Context, session *DeviceCodeSession) error
// DeviceCodeGet 根据设备码获取会话
DeviceCodeGet(ctx context.Context, deviceCode string) (*DeviceCodeSession, error)
// DeviceCodeGetByUserCode 根据用户码获取会话 (用于用户授权页面)
DeviceCodeGetByUserCode(ctx context.Context, userCode string) (*DeviceCodeSession, error)
// DeviceCodeUpdate 更新会话状态 (例如用户同意后)
DeviceCodeUpdate(ctx context.Context, deviceCode string, session *DeviceCodeSession) error
// DeviceCodeDelete 删除设备码会话及其关联索引
DeviceCodeDelete(ctx context.Context, deviceCode string) error
}
type Discovery ¶
type Discovery struct {
Issuer string `json:"issuer"`
AuthorizationEndpoint string `json:"authorization_endpoint"`
TokenEndpoint string `json:"token_endpoint"`
JWKSURI string `json:"jwks_uri"`
UserInfoEndpoint string `json:"userinfo_endpoint,omitempty"`
RevocationEndpoint string `json:"revocation_endpoint,omitempty"`
IntrospectionEndpoint string `json:"introspection_endpoint,omitempty"`
EndSessionEndpoint string `json:"end_session_endpoint,omitempty"`
RegistrationEndpoint string `json:"registration_endpoint,omitempty"`
DeviceAuthorizationEndpoint string `json:"device_authorization_endpoint,omitempty"`
PushedAuthorizationRequestEndpoint string `json:"pushed_authorization_request_endpoint,omitempty"` // RFC 9126
// 关键能力标识
ScopesSupported []string `json:"scopes_supported,omitempty"`
ResponseTypesSupported []string `json:"response_types_supported"`
ResponseModesSupported []string `json:"response_modes_supported,omitempty"`
GrantTypesSupported []string `json:"grant_types_supported,omitempty"`
SubjectTypesSupported []string `json:"subject_types_supported"`
IDTokenSigningAlgValuesSupported []string `json:"id_token_signing_alg_values_supported"`
TokenEndpointAuthMethodsSupported []string `json:"token_endpoint_auth_methods_supported,omitempty"`
ClaimsSupported []string `json:"claims_supported,omitempty"`
// PKCE 支持
CodeChallengeMethodsSupported []string `json:"code_challenge_methods_supported,omitempty"`
}
Discovery 定义了完整的 OpenID Provider 元数据 参见: RFC 8414, OIDC Discovery 1.0
type DistributedLock ¶
type DistributedLock interface {
// Lock 尝试获取锁
// ttl: 锁的自动过期时间
// 返回: true 如果获取成功, false 如果已被占用
Lock(ctx context.Context, key string, ttl time.Duration) (bool, error)
// Unlock 释放锁
Unlock(ctx context.Context, key string) error
}
DistributedLock 定义了分布式锁接口 用于密钥轮换等需要互斥的操作
type EndSessionRequest ¶
type EndSessionRequest struct {
IDTokenHint string
PostLogoutRedirectURI string
State string
// AccessToken 当前有效的 Access Token (可选)
// 如果提供,将被加入黑名单以实现即时登出
AccessToken string
}
EndSessionRequest RP-Initiated Logout Request
type Error ¶
type Error struct {
Code string `json:"error"` // e.g. "invalid_request"
Description string `json:"error_description"` // e.g. "Missing client_id"
StatusCode int `json:"-"` // HTTP 状态码 (仅用于 Token 端点)
}
Error 代表一个标准的 OAuth2 错误
func AccessDeniedError ¶
AccessDeniedError 创建 access_denied 错误 (HTTP 403)
func AuthorizationPendingError ¶
AuthorizationPendingError 创建 authorization_pending 错误 (HTTP 400) 用于 Device Flow
func ExpiredTokenError ¶
ExpiredTokenError 创建 expired_token 错误 (HTTP 400) 用于 Device Flow
func InvalidClientError ¶
InvalidClientError 创建 invalid_client 错误 (HTTP 401)
func InvalidGrantError ¶
InvalidGrantError 创建 invalid_grant 错误 (HTTP 400)
func InvalidRequestError ¶
InvalidRequestError 创建 invalid_request 错误 (HTTP 400)
func InvalidScopeError ¶
InvalidScopeError 创建 invalid_scope 错误 (HTTP 400)
func ServerError ¶ added in v0.3.0
ServerError 创建 server_error 错误 (HTTP 500)
func ServerErrorWithDescription ¶
ServerError 创建 server_error 错误 (HTTP 500)
func SlowDownError ¶
SlowDownError 创建 slow_down 错误 (HTTP 400) 用于 Device Flow
func TemporarilyUnavailableError ¶
TemporarilyUnavailableError 创建 temporarily_unavailable 错误 (HTTP 503)
func UnauthorizedClientError ¶
UnauthorizedClientError 创建 unauthorized_client 错误 (HTTP 400)
func UnsupportedGrantTypeError ¶
UnsupportedGrantTypeError 创建 unsupported_grant_type 错误 (HTTP 400)
func (*Error) PublicMessage ¶
PublicMessage 实现 httpx.PublicError 接口 (隐式) OAuth2 错误(如 invalid_grant)需要返回给客户端以供调试或处理,因此视为 safe。
type GCWorker ¶
type GCWorker struct {
// contains filtered or unexported fields
}
GCWorker 垃圾回收 Worker 定期调用 Persistence.Cleanup() 清理过期数据
func NewGCWorker ¶
func NewGCWorker(persistence Persistence, interval time.Duration) *GCWorker
NewGCWorker 创建 GC Worker interval: 清理间隔,建议 1 小时
type Hash256 ¶
type Hash256 []byte
Hash256 自定义类型,零依赖
func (Hash256) MarshalJSON ¶
func (*Hash256) UnmarshalJSON ¶
type Hasher ¶
type Hasher interface {
// Hash 对给定的明文密码进行哈希处理。
// 返回哈希后的字节切片或错误。
Hash(ctx context.Context, password []byte) ([]byte, error)
// Compare 将明文密码与已有的哈希值进行比较。
// 如果匹配,则返回nil;否则返回错误。
Compare(ctx context.Context, hashedPassword []byte, password []byte) error
}
Hasher 定义了密码哈希和验证的接口。
type IDToken ¶
type IDToken SecretString
type IDTokenClaims ¶
type IDTokenClaims struct {
jwt.RegisteredClaims
// OIDC 特定声明
Nonce string `json:"nonce,omitempty"` // 关联客户端会话的字符串值,用于缓解重放攻击
AuthTime int64 `json:"auth_time,omitempty"` // 终端用户认证发生的时间
AuthorizedParty string `json:"azp,omitempty"` // 授权方 (Authorized Party),当 aud 包含多个值时必须存在
AtHash string `json:"at_hash,omitempty"` // Access Token 的哈希值,用于验证 Access Token
CHash string `json:"c_hash,omitempty"` // Code 的哈希值
// Profile 声明 (标准 Scope: profile, email, phone)
Name *string `json:"name,omitempty"`
PreferredUsername *string `json:"preferred_username,omitempty"`
Picture *string `json:"picture,omitempty"`
Email *string `json:"email,omitempty"`
EmailVerified *bool `json:"email_verified,omitempty"` // 指针用于区分 false 和 null
PhoneNumber *string `json:"phone_number,omitempty"`
PhoneNumberVerified *bool `json:"phone_number_verified,omitempty"`
}
IDTokenClaims 表示 OIDC ID Token 的标准载荷。 参见: OIDC Core 1.0, Section 2.
func (*IDTokenClaims) SignedString ¶
func (ic *IDTokenClaims) SignedString(method jwt.SigningMethod, privateKey crypto.PrivateKey) (IDToken, error)
type IntrospectionRequest ¶ added in v0.3.3
type IntrospectionRequest struct {
Token string `form:"token" json:"token"` // 必填
TokenTypeHint string `form:"token_type_hint" json:"token_type_hint"` // 选填
// Client 认证信息 (自动通过 ClientAuthBinder 注入)
ClientID string `form:"client_id" json:"client_id"`
ClientSecret string `form:"client_secret" json:"client_secret"`
}
IntrospectionRequest 定义 RFC 7662 请求体 必须支持 Form 表单和 Basic Auth
type IntrospectionResponse ¶
type IntrospectionResponse 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"`
// DPoP (RFC 9449): Confirmation claim
Cnf map[string]interface{} `json:"cnf,omitempty"`
}
IntrospectionResponse RFC 7662 Introspection Response
func Introspect ¶
func Introspect(ctx context.Context, storage Storage, verifier TokenVerifier, tokenStr, clientIDStr, clientSecret string, hasher Hasher) (*IntrospectionResponse, error)
Introspect 验证 Token 状态 RFC 7662: OAuth 2.0 Token Introspection
type Issuer ¶
type Issuer struct {
// contains filtered or unexported fields
}
Issuer 负责生成符合 OIDC/OAuth2 标准的 Token
func NewIssuer ¶
func NewIssuer(cfg IssuerConfig, keyManager *KeyManager) (*Issuer, error)
NewIssuer 创建一个新的 Token 发行者
func (*Issuer) IssueClientCredentialsToken ¶
func (g *Issuer) IssueClientCredentialsToken(ctx context.Context, req *IssuerRequest) (*IssuerResponse, error)
IssueClientCredentialsToken 专门用于客户端凭证模式 只生成 Access Token,不生成 Refresh Token,不生成 ID Token
func (*Issuer) IssueOAuthTokens ¶
func (g *Issuer) IssueOAuthTokens(ctx context.Context, req *IssuerRequest) (*IssuerResponse, error)
func (*Issuer) IssueOIDCTokens ¶
func (g *Issuer) IssueOIDCTokens(ctx context.Context, req *IssuerRequest) (*IssuerResponse, error)
IssueOIDCTokens 生成 OIDC 套件 (ID Token + Access Token + Refresh Token)
func (*Issuer) IssuePasswordResetAccessToken ¶ added in v0.3.0
func (g *Issuer) IssuePasswordResetAccessToken(ctx context.Context, req *IssuerRequest) (*IssuerResponse, error)
IssuePasswordResetAccessToken 生成密码修改 AccessToken
func (*Issuer) RefreshOAuthTokens ¶
func (g *Issuer) RefreshOAuthTokens(ctx context.Context, req *IssuerRequest) (*IssuerResponse, error)
RefreshOAuthTokens 刷新 OAuth2 Token 注意:调用者负责验证旧 Refresh Token 的合法性,并将旧 Token 关联的信息填入 req
func (*Issuer) RefreshOIDCTokens ¶
func (g *Issuer) RefreshOIDCTokens(ctx context.Context, req *IssuerRequest) (*IssuerResponse, error)
RefreshOIDCTokens 刷新 OIDC Token 区别:ID Token 在刷新时不应包含 Nonce (OIDC Core 1.0 Section 12.1)
func (*Issuer) SecretManager ¶
func (i *Issuer) SecretManager() *SecretManager
type IssuerConfig ¶
type IssuerConfig struct {
Issuer string
SecretManager *SecretManager
// 默认 TTL (兜底策略)
AccessTokenTTL time.Duration
IDTokenTTL time.Duration
RefreshTokenTTL time.Duration
RefreshTokenGracePeriod time.Duration
}
IssuerConfig 配置签发的默认参数
type IssuerRequest ¶
type IssuerRequest struct {
ClientID BinaryUUID
UserID BinaryUUID // Subject (sub)
Scopes string // Space delimited scopes
Audience []string // Resource Server URIs
Nonce string // 仅用于 Implicit/AuthCode Flow 的 Issue 阶段
Code Code // 关联的 Authorization Code (如果适用,用于计算 c_hash)
AuthTime time.Time // 用户完成认证的时间
// --- TTL 覆盖策略 ---
// 如果设置了以下字段(大于0),则使用该时间;否则使用 Config 中的默认时间。
AccessTokenDuration time.Duration
RefreshTokenDuration time.Duration
IDTokenDuration time.Duration
// --- User Profile ---
Name *string
PreferredUsername *string
Picture *string
Email *string
EmailVerified *bool
PhoneNumber *string
PhoneNumberVerified *bool
// DPoP (RFC 9449): JWK Thumbprint from DPoP proof
// 如果不为空,将在 Access Token 中添加 cnf.jkt claim
DPoPJKT string
}
IssuerRequest 包含生成 Token 所需的上下文信息
type IssuerResponse ¶
type IssuerResponse struct {
TokenType string `json:"token_type"` // Bearer
AccessToken string `json:"access_token"`
RefreshToken string `json:"refresh_token,omitempty"`
IDToken string `json:"id_token,omitempty"` // 仅在 OIDC 流程中存在
ExpiresIn int64 `json:"expires_in"`
Scope string `json:"scope,omitempty"`
}
IssuerResponse OAuth2 /oauth/token 响应结构
func DeviceTokenExchange ¶
func DeviceTokenExchange(ctx context.Context, storage Storage, issuer *Issuer, req *TokenRequest) (*IssuerResponse, error)
DeviceTokenExchange 处理设备码换取 Token
func ExchangeClientCredentials ¶
func ExchangeClientCredentials(ctx context.Context, storage ClientStorage, hasher Hasher, issuer *Issuer, req *TokenRequest) (*IssuerResponse, error)
ExchangeClientCredentials 处理 client_credentials 流程 (M2M)
func ExchangeCode ¶
func ExchangeCode(ctx context.Context, storage Storage, hasher Hasher, issuer *Issuer, req *TokenRequest) (*IssuerResponse, error)
ExchangeCode 用于处理 authorization_code 流程
func PasswordGrant ¶
func PasswordGrant(ctx context.Context, storage Storage, hasher Hasher, issuer *Issuer, req *TokenRequest) (*IssuerResponse, error)
PasswordGrant 生产存根实现,总是返回 "unsupported grant type" 错误。 这个函数确保了在生产构建中调用 password grant 逻辑会安全地失败,并且二进制文件中不包含任何实际的处理代码。
func RefreshTokens ¶
func RefreshTokens(ctx context.Context, storage Storage, secretManager *SecretManager, hasher Hasher, issuer *Issuer, req *TokenRequest) (*IssuerResponse, error)
RefreshTokens 用于处理 refresh_token 流程
type JSONWebKey ¶
type JSONWebKey struct {
Kty string `json:"kty"` // Key Type (RSA, EC, OKP)
Kid string `json:"kid,omitempty"` // Key ID
Use string `json:"use,omitempty"` // Public Key Use (sig, enc)
Alg string `json:"alg,omitempty"` // Algorithm (RS256, ES256, EdDSA...)
// RSA 字段
N string `json:"n,omitempty"` // Modulus (Base64URL)
E string `json:"e,omitempty"` // Exponent (Base64URL)
// ECDSA / Ed25519 字段
Crv string `json:"crv,omitempty"` // Curve (P-256, P-384, P-521, Ed25519)
X string `json:"x,omitempty"` // X Coordinate (Base64URL)
Y string `json:"y,omitempty"` // Y Coordinate (Base64URL), Ed25519 不需要此字段
}
JSONWebKey 表示单个 JWK 的结构。
func PublicKeyToJWK ¶
func PublicKeyToJWK(pub crypto.PublicKey, kid, alg string) (JSONWebKey, error)
PublicKeyToJWK 将标准库的 crypto.PublicKey 转换为 JWK 结构体。
func (*JSONWebKey) Thumbprint ¶
func (jwk *JSONWebKey) Thumbprint() (string, error)
Thumbprint 根据 RFC 7638 计算 JWK Thumbprint (SHA-256) 常用于生成 kid
type JSONWebKeySet ¶
type JSONWebKeySet struct {
Keys []JSONWebKey `json:"keys"`
}
JSONWebKeySet 表示 JWKS 端点返回的顶级 JSON 结构。
type JWK ¶ added in v0.3.0
type JWK struct {
// KID: Key ID,主键
KID string `db:"kid"`
// JWK: 包含私钥的大段 JSON 文本,使用 text 类型
JWK SecretString `db:"jwk"`
CreatedAt time.Time `db:"created_at"`
}
JWK 存储轮转的加密密钥
type Key ¶
type Key interface {
crypto.PrivateKey
Public() crypto.PublicKey
Equal(x crypto.PrivateKey) bool
Sign(rand io.Reader, digest []byte, opts crypto.SignerOpts) ([]byte, error)
}
Key 接口定义了一个可用于签名的私钥所需的方法。
func LoadOrGenerateKey ¶
LoadOrGenerateKey 尝试从指定路径加载私钥。 如果文件存在,则加载它;如果不存在,则生成一个新密钥并保存。
type KeyManager ¶
type KeyManager struct {
// contains filtered or unexported fields
}
KeyManager 负责管理服务端的私钥集合。 它支持密钥轮换、JWKS 导出以及查找当前签名密钥。 现在的实现是无状态的(依赖 KeyStorage),但保留了本地缓存以提高性能。
func NewKeyManager ¶
func NewKeyManager(storage KeyStorage, cacheTTL time.Duration) *KeyManager
NewKeyManager 创建密钥管理器
func (*KeyManager) ExportJWKS ¶
func (km *KeyManager) ExportJWKS(ctx context.Context) (*JSONWebKeySet, error)
ExportJWKS 导出所有公钥为 JWKS 结构。
func (*KeyManager) GetKeyInternal ¶
GetKeyInternal 获取私钥 (Key 接口)
func (*KeyManager) GetSigningKey ¶
GetSigningKey 获取当前用于签名的私钥和 kid。
func (*KeyManager) JWKGetSigning ¶ added in v0.3.0
func (km *KeyManager) JWKGetSigning(ctx context.Context) (string, error)
JWKGetSigning 获取当前签名密钥 ID
func (*KeyManager) ListKeys ¶
func (km *KeyManager) ListKeys(ctx context.Context) ([]string, error)
ListKeys 返回所有密钥的 KID 列表
func (*KeyManager) RemoveKey ¶
func (km *KeyManager) RemoveKey(ctx context.Context, kid string) error
RemoveKey 删除指定的密钥。
func (*KeyManager) SetSigningKeyID ¶
func (km *KeyManager) SetSigningKeyID(ctx context.Context, kid string) error
SetSigningKeyID 指定哪个 kid 用于签名。
type KeyProvider ¶
type KeyProvider interface {
// GetKey 获取指定版本的密钥
GetKey(ctx context.Context, kid string) ([]byte, error)
// GetActiveKey 获取当前活跃的签名密钥
GetActiveKey(ctx context.Context) (string, []byte, error)
// ListKeys 列出所有可用密钥(用于验证)
// 返回 map[kid]key,包括活跃密钥和处于宽限期的旧密钥
ListKeys(ctx context.Context) (map[string][]byte, error)
}
KeyProvider 定义密钥获取接口,支持内存、KMS、HSM 等多种实现 这是依赖倒置原则的体现:核心逻辑依赖抽象接口,而非具体实现
type KeyRotationConfig ¶
type KeyRotationConfig struct {
// RotationInterval 密钥轮换间隔(例如 30 天)
RotationInterval time.Duration
// GracePeriod 旧密钥保留期,用于验证旧 Token(例如 7 天)
GracePeriod time.Duration
// KeyType 生成的密钥类型
KeyType KeyType
// EnableAutoRotate 是否启用自动定时轮换
EnableAutoRotate bool
// CleanupInterval 清理过期密钥的检查间隔
// 如果为 0,默认为 1 分钟
// 测试时可设置为较短时间(如 1 秒)
CleanupInterval time.Duration
}
KeyRotationConfig 密钥轮换配置
type KeyRotationScheduler ¶
type KeyRotationScheduler struct {
// contains filtered or unexported fields
}
KeyRotationScheduler 密钥轮换调度器 负责编排密钥的完整生命周期:生成 → 签名 → 宽限期 → 删除
func NewKeyRotationScheduler ¶
func NewKeyRotationScheduler(manager *KeyManager, lock DistributedLock, config KeyRotationConfig) *KeyRotationScheduler
NewKeyRotationScheduler 创建密钥轮换调度器
func (*KeyRotationScheduler) GetCurrentKeyID ¶
func (s *KeyRotationScheduler) GetCurrentKeyID() string
GetCurrentKeyID 获取当前签名密钥 ID
func (*KeyRotationScheduler) GetPendingDeletes ¶
func (s *KeyRotationScheduler) GetPendingDeletes() map[string]time.Time
GetPendingDeletes 获取待删除密钥列表(用于监控)
func (*KeyRotationScheduler) RotateNow ¶
func (s *KeyRotationScheduler) RotateNow(ctx context.Context) error
RotateNow 立即触发一次密钥轮换 适用于安全事件响应或手动干预
type KeySource ¶
type KeySource interface {
// GetKey 根据 Key ID (kid) 返回对应的公钥。
// 如果 kid 为空,且源中只有一个 key,应返回该 key。
GetKey(ctx context.Context, kid string) (crypto.PublicKey, error)
}
KeySource 定义了验证器如何获取公钥。 它可以是静态的 JWKS,也可以是远程 URL (OIDC Discovery)。
type KeyStorage ¶
type KeyStorage interface {
// JWKSave 存储一个 JWK (包含私钥)
// 如果 key 已存在,应该覆盖或返回错误(取决于实现,通常是覆盖)
JWKSave(ctx context.Context, key jwk.Key) error
// JWKGet 获取指定 kid 的 JWK
JWKGet(ctx context.Context, kid string) (jwk.Key, error)
// JWKList 获取所有存储的 JWK
JWKList(ctx context.Context) ([]jwk.Key, error)
// JWKDelete 删除指定 kid 的 JWK
JWKDelete(ctx context.Context, kid string) error
// JWKMarkSigning 存储当前签名密钥 ID
JWKMarkSigning(ctx context.Context, kid string) error
// JWKGetSigning 获取当前签名密钥 ID
JWKGetSigning(ctx context.Context) (string, error)
}
KeyStorage 定义了私钥的持久化存储接口 必须支持分布式环境下的并发访问
type MemoryKeyProvider ¶
type MemoryKeyProvider struct {
// contains filtered or unexported fields
}
MemoryKeyProvider 内存实现,保持现有行为 适用于开发环境和不需要 KMS 的简单部署
func NewMemoryKeyProvider ¶
func NewMemoryKeyProvider() *MemoryKeyProvider
NewMemoryKeyProvider 创建内存密钥提供者
func (*MemoryKeyProvider) AddKey ¶
func (m *MemoryKeyProvider) AddKey(kid string, key []byte) error
AddKey 添加新密钥
func (*MemoryKeyProvider) CleanupExpiredKeys ¶
func (m *MemoryKeyProvider) CleanupExpiredKeys(ctx context.Context) int
CleanupExpiredKeys 清理已过期的 deprecated keys 应该定期调用(例如通过 cron)
func (*MemoryKeyProvider) GetActiveKey ¶
GetActiveKey 实现 KeyProvider 接口
func (*MemoryKeyProvider) RemoveKey ¶
func (m *MemoryKeyProvider) RemoveKey(kid string) error
RemoveKey 删除密钥 注意:不能删除当前活跃的密钥
func (*MemoryKeyProvider) RotateKey ¶
func (m *MemoryKeyProvider) RotateKey(newKID string, newKey []byte, gracePeriod time.Duration) error
RotateKey 轮换密钥(优雅轮换) 1. 添加新密钥 2. 切换活跃密钥 3. 将旧密钥标记为 deprecated(但保留验证能力)
func (*MemoryKeyProvider) SetActiveKey ¶
func (m *MemoryKeyProvider) SetActiveKey(kid string) error
SetActiveKey 设置活跃密钥
type PARRequest ¶
type PARRequest struct {
// 客户端认证信息 (必需)
ClientID string `form:"client_id" json:"client_id"`
ClientSecret string `form:"client_secret" json:"client_secret"` // 对于机密客户端
// 授权请求参数 (与标准 /authorize 端点相同)
RedirectURI string `form:"redirect_uri" json:"redirect_uri"`
ResponseType string `form:"response_type" json:"response_type"`
Scope string `form:"scope" json:"scope"`
State string `form:"state" json:"state"`
Nonce string `form:"nonce" json:"nonce"`
// PKCE
CodeChallenge string `form:"code_challenge" json:"code_challenge"`
CodeChallengeMethod string `form:"code_challenge_method" json:"code_challenge_method"`
// DPoP (RFC 9449): JWK Thumbprint from DPoP proof
// 由 HTTP Handler 验证 DPoP Proof 后提取并传入
DPoPJKT string `form:"-" json:"-"`
// 扩展参数
AdditionalParams map[string]string `form:"-" json:"-"`
}
PARRequest 表示推送授权请求的参数 RFC 9126 Section 2
type PARResponse ¶
type PARResponse struct {
RequestURI string `json:"request_uri"` // 格式: urn:ietf:params:oauth:request_uri:...
ExpiresIn int `json:"expires_in"` // 秒数,典型值 60
}
PARResponse 表示 PAR 端点的响应 RFC 9126 Section 2.2
func PushedAuthorization ¶
func PushedAuthorization( ctx context.Context, storage Storage, hasher Hasher, req *PARRequest, ) (*PARResponse, error)
PushedAuthorization 处理推送授权请求 RFC 9126: 客户端通过后端通道提交授权参数,获得 request_uri
安全要求: - 必须验证客户端身份 (Client Secret 或 mTLS) - 所有授权参数必须经过验证 - request_uri 只能使用一次 - TTL 应较短 (推荐 60 秒)
type PARStorage ¶
type PARStorage interface {
// PARSessionSave 保存 PAR 会话
// requestURI: 格式为 "urn:ietf:params:oauth:request_uri:<唯一标识>"
// req: 完整的授权请求参数
// ttl: 会话有效期,RFC 建议 60 秒
PARSessionSave(ctx context.Context, requestURI string, req *AuthorizeRequest, ttl time.Duration) error
// PARSessionConsume 获取并删除 PAR 会话(原子操作)
// PAR request_uri 只能使用一次
PARSessionConsume(ctx context.Context, requestURI string) (*AuthorizeRequest, error)
}
PARStorage 管理推送授权请求 (Pushed Authorization Requests) 会话 RFC 9126: OAuth 2.0 Pushed Authorization Requests
type Persistence ¶
type Persistence interface {
ClientStorage
KeyStorage // JWK (基础设施)
TokenStorage // Refresh Token (长效)
UserInfoGetter // 用户数据
UserAuthenticator
// Cleanup 清理过期的数据 (Garbage Collection)
// 此方法应删除已过期的 RefreshToken, AuthCode, DeviceCode 等临时数据
// 建议由后台 Worker 定期调用(例如每小时一次)
// 返回被清理的记录数和错误
Cleanup(ctx context.Context) (deleted int64, err error)
Close()
}
Persistence 负责长久存储的数据 建议实现:GORM (PostgreSQL)
type RefreshToken ¶
type RefreshToken SecretString
func IssueStructuredRefreshToken ¶
func IssueStructuredRefreshToken(ctx context.Context, sm *SecretManager, userID string, ttl time.Duration) (RefreshToken, error)
IssueStructuredRefreshToken 生成一个结构化的 Refresh Token
func (RefreshToken) HashForDB ¶
func (t RefreshToken) HashForDB() Hash256
HashForDB 刷新 token 使用 sha256 进行 hash 如果是结构化 Token (kid.meta.rand.sig),只 Hash 随机部分 (rand) 这配合签名验证可防止数据库 DoS,同时保证数据库索引的唯一性和安全性
type RefreshTokenSession ¶
type RefreshTokenSession struct {
// ID 默认为主键,无需标签
// GORM 默认将 Hash256 映射为对应类型(需实现 Scanner/Valuer)
ID Hash256
// 默认映射为 client_id,但在 db 标签中指定 index
ClientID BinaryUUID `db:"client_id"`
// 默认映射为 user_id,指定 index
UserID BinaryUUID `db:"user_id"`
// 指定数据库类型为 text
Scope string `db:"scope"`
// 默认映射 auth_time
AuthTime time.Time
// 默认映射 expires_at,指定 index
ExpiresAt time.Time `db:"expires_at"`
// 上下文信息
Nonce string // 默认 varchar
ACR string // 默认 varchar
AMR StringSlice `db:"amr"`
}
RefreshTokenSession 包含刷新令牌关联的上下文信息。
func (RefreshTokenSession) TableName ¶ added in v0.3.0
func (RefreshTokenSession) TableName() string
type RegisteredClient ¶
type RegisteredClient interface {
// GetID 返回客户端 ID
GetID() BinaryUUID
// GetRedirectURIs 返回注册的回调地址列表
GetRedirectURIs() []string
// GetGrantTypes 返回允许的授权类型 (e.g., "authorization_code", "refresh_token")
GetGrantTypes() []string
// GetScope 返回客户端注册的允许 Scopes 字符串 (空格分隔)
// OIDC Core 逻辑会用此与请求的 Scope 取交集
GetScope() string
// IsConfidential 返回是否为机密客户端 (Confidential vs Public)
IsConfidential() bool
// ValidateSecret 验证输入的明文密钥。
// 对于 Public Client,此方法应直接返回 nil。
// 对于 Confidential Client,实现层应处理哈希比对 (如 bcrypt/argon2)。
ValidateSecret(ctx context.Context, hasher Hasher, secret string) error
// 提供给Redis一个序列化和反序列化的方法
Serialize() (string, error)
Deserialize(string) error
// Metadata 获取客户端的元数据以便进行更新
Metadata() *ClientMetadata
}
RegisteredClient 定义了 OIDC 协议流程中所需的客户端视图。
func AuthenticateClient ¶
func AuthenticateClient(ctx context.Context, storage ClientStorage, clientIDStr, clientSecret string, hasher Hasher) (RegisteredClient, error)
AuthenticateClient 验证客户端身份
func ListClient ¶
func ListClient(ctx context.Context, storage ClientStorage, query ListQuery) ([]RegisteredClient, error)
ListClient 列出所有客户端
func RequestAuthorize ¶
func RequestAuthorize(ctx context.Context, storage Storage, req *AuthorizeRequest) (RegisteredClient, error)
RequestAuthorize 校验授权请求的基本参数。 这一步通常在显示登录页面或授权同意页面之前调用。 如果返回 error,调用者应直接向用户显示错误页,而不是重定向(因为 RedirectURI 可能尚未验证)。
PAR 支持 (RFC 9126): - 如果 req.RequestURI 存在,从 PARStorage 加载完整请求参数 - request_uri 只能使用一次
type RemoteKeySet ¶
type RemoteKeySet struct {
// contains filtered or unexported fields
}
RemoteKeySet 实现了 KeySource 接口。 它能够从远程 JWKS URI 获取公钥,并支持 Stale-While-Revalidate 缓存机制。
func NewRemoteKeySet ¶
func NewRemoteKeySet(ctx context.Context, jwksURI string, httpClient *http.Client, opts ...RemoteKeySetOption) *RemoteKeySet
NewRemoteKeySet 创建一个新的远程密钥集。 ctx: 用于控制 HTTP 请求的生命周期。 jwksURI: 远程 JWKS 地址。
type RemoteKeySetOption ¶
type RemoteKeySetOption func(*RemoteKeySet)
RemoteKeySetOption allows configuring RemoteKeySet
func WithCacheDuration ¶
func WithCacheDuration(d time.Duration) RemoteKeySetOption
WithCacheDuration sets the default cache duration
type ReplayCache ¶
type ReplayCache interface {
// CheckAndStore 原子性地检查 JTI 是否已使用,若未使用则存储。
// 返回 true 表示 JTI 已存在 (重放攻击),false 表示首次使用。
// ttl 参数指定 JTI 在缓存中的有效期。
CheckAndStore(ctx context.Context, jti string, ttl time.Duration) (bool, error)
}
ReplayCache 定义了防重放攻击的缓存接口。 用于 DPoP (RFC 9449) 的 JTI (JWT ID) 去重。
type ResourceVerifier ¶
type ResourceVerifier struct {
// contains filtered or unexported fields
}
ResourceVerifier 用于资源服务器验证 OIDC ID Token。
func NewResourceVerifier ¶
func NewResourceVerifier(issuer, resourceURI string, keySet KeySource, trustedClients []string) *ResourceVerifier
NewResourceVerifier 创建一个新的客户端验证器。 issuer: 必须完全匹配 Token 中的 iss。 resourceURI: 必须包含在 Token 的 aud 中。 trustedClients: 如果不为nil, 会限制使用本服务的请求客户端
func (*ResourceVerifier) SetSupportedSigningAlgs ¶
func (v *ResourceVerifier) SetSupportedSigningAlgs(algs []string)
SetSupportedSigningAlgs 设置支持的签名算法
func (*ResourceVerifier) Verify ¶
func (v *ResourceVerifier) Verify(ctx context.Context, rawToken string) (*AccessTokenClaims, error)
Verify 解析并验证原始 ID Token 字符串。
type RevocationRequest ¶
type RevocationRequest struct {
Token string `form:"token" json:"token"`
TokenTypeHint string `form:"token_type_hint" json:"token_type_hint"` // "access_token" 或 "refresh_token" (可选)
ClientID string `form:"client_id" json:"client_id"`
ClientSecret string `form:"client_secret" json:"client_secret"`
}
RevocationRequest 封装 RFC 7009 撤销请求参数
type RevocationStorage ¶
type RevocationStorage interface {
// AccessTokenRevoke 将 JTI (JWT ID) 加入黑名单,直到 expiration 时间。
AccessTokenRevoke(ctx context.Context, jti string, expiration time.Time) error
// AccessTokenIsRevoked 检查 JTI 是否在黑名单中。
AccessTokenIsRevoked(ctx context.Context, jti string) (bool, error)
}
RevocationStorage 用于管理 Access Token 的黑名单 (Revocation JWKList)。 Access Token 通常是无状态 JWT,一旦签发无法修改,撤销只能通过黑名单 (JTI) 实现。
type SecretBytes ¶ added in v0.3.0
type SecretBytes []byte
SecretBytes 是一种自定义字节切片类型,用于防止敏感信息在日志中被意外打印。 注意:当用于存储密码或 Secret 的哈希值时,应确保存储的是哈希后的值。
func (SecretBytes) GoString ¶ added in v0.3.0
func (s SecretBytes) GoString() string
Go 语法格式化接口 (%#v) - 往常容易被忽略的泄露点
func (SecretBytes) MarshalJSON ¶ added in v0.3.0
func (s SecretBytes) MarshalJSON() ([]byte, error)
MarshalJSON 方法确保在将配置序列化为JSON时,敏感字段也被屏蔽。
func (*SecretBytes) Scan ¶ added in v0.3.0
func (s *SecretBytes) Scan(value interface{}) error
Scan 实现 sql.Scanner 接口, 告诉 Go 如何从数据库读取值到 Bytes
func (SecretBytes) String ¶ added in v0.3.0
func (s SecretBytes) String() string
Bytes 方法重写了默认行为,使其在被格式化打印时返回一个屏蔽后的字符串。
type SecretManager ¶
type SecretManager struct {
// contains filtered or unexported fields
}
SecretManager 管理 HMAC 密钥,用于 Refresh Token 签名 现在使用 KeyProvider 抽象,支持内存、KMS、HSM 等多种实现
func NewSecretManagerWithProvider ¶
func NewSecretManagerWithProvider(provider KeyProvider) *SecretManager
NewSecretManagerWithProvider 创建密钥管理器(使用自定义提供者)
func (*SecretManager) AddKey ¶
func (s *SecretManager) AddKey(id string, hexSecret string) error
AddKey 添加密钥(向后兼容的便捷方法) 注意:仅在 provider 是 MemoryKeyProvider 时可用
func (*SecretManager) CleanupExpiredKeys ¶
func (s *SecretManager) CleanupExpiredKeys() (int, error)
CleanupExpiredKeys 清理已过期的密钥 返回清理的密钥数量
func (*SecretManager) GetSigningKey ¶
func (s *SecretManager) GetSigningKey(ctx context.Context) ([]byte, string)
GetSigningKey 获取签名用的密钥 (HMAC Key) 返回 (key, kid)
func (*SecretManager) GetVerificationKey ¶
GetVerificationKey 根据 Token 中的 kid 获取验证密钥
func (*SecretManager) RotateKey ¶
func (s *SecretManager) RotateKey(newKID string, newHexSecret string, gracePeriod time.Duration) error
RotateKey 轮换密钥(优雅轮换) gracePeriod: 旧密钥保留用于验证的时间
func (*SecretManager) SetActiveKey ¶
func (s *SecretManager) SetActiveKey(kid string) error
SetActiveKey 设置活跃密钥(向后兼容的便捷方法) 注意:仅在 provider 是 MemoryKeyProvider 时可用
type SecretString ¶ added in v0.3.0
type SecretString string
SecretString 是一种自定义字符串类型,用于防止敏感信息在日志中被意外打印。 注意:当用于存储 Client Secret 时,此字段应存储哈希后的值,而非明文。 在 ClientMetadata 中,Secret 字段通过 Hasher 接口哈希后再赋值给此类型。
func (SecretString) GoString ¶ added in v0.3.0
func (s SecretString) GoString() string
Go 语法格式化接口 (%#v) - 往常容易被忽略的泄露点
func (SecretString) MarshalJSON ¶ added in v0.3.0
func (s SecretString) MarshalJSON() ([]byte, error)
MarshalJSON 方法确保在将配置序列化为JSON时,敏感字段也被屏蔽。
func (*SecretString) Scan ¶ added in v0.3.0
func (s *SecretString) Scan(value interface{}) error
Scan 实现 sql.Scanner 接口, 告诉 Go 如何从数据库读取值到 String
func (SecretString) String ¶ added in v0.3.0
func (s SecretString) String() string
String 方法重写了默认行为,使其在被格式化打印时返回一个屏蔽后的字符串。
type Server ¶
type Server struct {
// contains filtered or unexported fields
}
Server 是 OIDC 协议的核心控制器。 它是一个 Facade (门面),组合了 Authorizer, Issuer, TokenHandler 等组件。 调用者应通过 NewServer 创建实例,并将其挂载到 HTTP 路由上。
func NewServer ¶
func NewServer(cfg ServerConfig) (*Server, error)
NewServer 初始化一个新的 OIDC 服务。 注意:初始化后,必须: 1. 调用 server.KeyManager().Add(...) 添加至少一个签名密钥 (RSA/EC) 2. 调用 server.SecretManager().AddKey(...) 添加至少一个 HMAC 密钥 (用于 Refresh Token) 3. 调用 server.ValidateKeys() 验证密钥配置 4. 启动 HTTP 服务
func (*Server) ClientUpdate ¶ added in v0.3.0
func (s *Server) ClientUpdate(ctx context.Context, req *ClientUpdateRequest) (*ClientRegistrationResponse, error)
ClientUpdate 处理动态客户端更新
func (*Server) Config ¶
func (s *Server) Config() *ServerConfig
func (*Server) DeviceAuthorization ¶
func (s *Server) DeviceAuthorization(ctx context.Context, req *DeviceAuthorizationRequest) (*DeviceAuthorizationResponse, error)
DeviceAuthorization 处理设备授权请求
func (*Server) Discovery ¶
Discovery 返回符合 OIDC Discovery 标准的元数据结构。 调用者应将其序列化为 JSON 并通过 /.well-known/openid-configuration 暴露。
func (*Server) EndSession ¶
EndSession 处理用户登出
func (*Server) Exchange ¶
func (s *Server) Exchange(ctx context.Context, req *TokenRequest) (resp *IssuerResponse, err error)
Exchange 处理 Token 交换
func (*Server) GetUserInfo ¶
GetUserInfo 获取用户信息
func (*Server) Introspect ¶
func (s *Server) Introspect(ctx context.Context, tokenStr, clientIDStr, clientSecret string) (*IntrospectionResponse, error)
Introspect 验证 Token 状态
func (*Server) KeyManager ¶
func (s *Server) KeyManager() *KeyManager
KeyManager 返回密钥管理器,用于添加、删除密钥或导出 JWKS。
func (*Server) ListClient ¶
ListClient 列出所有客户端
func (*Server) ParseAccessToken ¶
ParseAccessToken 解析并验证 Token 签名和 Issuer,但不检查撤销状态。
func (*Server) PushedAuthorization ¶
func (s *Server) PushedAuthorization(ctx context.Context, req *PARRequest) (*PARResponse, error)
PushedAuthorization 处理推送授权请求 (PAR - RFC 9126)
func (*Server) RegisterClient ¶
func (s *Server) RegisterClient(ctx context.Context, req *ClientRegistrationRequest) (*ClientRegistrationResponse, error)
RegisterClient 处理动态客户端注册
func (*Server) RequestAuthorize ¶
func (s *Server) RequestAuthorize(ctx context.Context, req *AuthorizeRequest) (client RegisteredClient, err error)
RequestAuthorize 校验授权请求
func (*Server) ResponseAuthorized ¶
func (s *Server) ResponseAuthorized(ctx context.Context, req *AuthorizeRequest) (redirectURL string, err error)
ResponseAuthorized 用户同意后生成重定向URL
func (*Server) RevokeToken ¶
func (s *Server) RevokeToken(ctx context.Context, req *RevocationRequest) error
RevokeToken 处理 Token 撤销
func (*Server) SecretManager ¶
func (s *Server) SecretManager() *SecretManager
SecretManager 返回 HMAC 密钥管理器,用于 Refresh Token 的签名管理。
func (*Server) StartBackgroundWorkers ¶
StartBackgroundWorkers 启动所有后台 Worker 应在 HTTP 服务启动之前调用 ctx 用于传递取消信号和 tracing context
func (*Server) StopBackgroundWorkers ¶
func (s *Server) StopBackgroundWorkers()
StopBackgroundWorkers 停止所有后台 Worker 应在 HTTP 服务关闭时调用
func (*Server) UnregisterClient ¶
UnregisterClient 处理动态客户端注销
func (*Server) ValidateKeys ¶
ValidateKeys 检查密钥管理器是否至少配置了一个签名密钥。 应在启动 HTTP 服务前调用,以尽早发现配置错误。
返回 ErrNoSigningKey 如果未配置任何签名密钥。
func (*Server) VerifyAccessToken ¶
func (s *Server) VerifyAccessToken(ctx context.Context, tokenStr string) (*AccessTokenClaims, error)
VerifyAccessToken 用于验证 Bearer Token 的有效性。 此实现不校验 Audience,因为 UserInfo 端点信任本 Issuer 签发的任何包含 openid scope 的 Token。
type ServerConfig ¶
type ServerConfig struct {
// Issuer 是服务的唯一标识符 (URL),例如 "https://auth.example.com"
Issuer string
// Storage 是数据持久层接口实现
Storage Storage
// Hasher 是密码哈希器
Hasher Hasher
// SecretManager 用于管理 Refresh Token 签名的对称密钥 (HMAC)
// 如果为 nil,NewServer 会初始化一个默认的 MemoryKeyProvider,但该 Provider 初始无密钥,
// 需要通过 server.SecretManager() 获取实例后添加密钥,或者在 Config 中直接传入配置好的实例。
SecretManager *SecretManager
// 令牌有效期配置 (若为 0,NewServer 会设置默认值)
CodeTTL time.Duration // 默认 5 分钟
AccessTokenTTL time.Duration // 默认 1 小时
RefreshTokenTTL time.Duration // 默认 30 天
IDTokenTTL time.Duration // 默认 1 小时
RefreshTokenGracePeriod time.Duration // 默认 30 秒
// SupportedSigningAlgs 支持的签名算法 (默认为 RS256, ES256)
SupportedSigningAlgs []string
// EnableGC 是否启用垃圾回收 Worker (默认为 true)
EnableGC bool
// GCInterval GC 执行间隔 (默认 1 小时)
GCInterval time.Duration
}
ServerConfig 用于初始化 OIDC Server 的配置
type StaticKeySet ¶
StaticKeySet 是 KeySource 的一个简单实现,用于基于本地 JWKS 验证 (单元测试或本地开发用)
func NewStaticKeySet ¶
func NewStaticKeySet() *StaticKeySet
type StringSlice ¶ added in v0.3.0
type StringSlice []string
StringSlice 用于在数据库中以 JSON 格式存储 []string
func (*StringSlice) Scan ¶ added in v0.3.0
func (ss *StringSlice) Scan(value interface{}) error
type TieredStorage ¶
type TieredStorage struct {
Persistence
Cache
}
TieredStorage implements a storage strategy that uses a fast Cache layer backed by a persistent Database layer.
Strategy:
- Reads: Read-Through (Cache -> Miss? -> DB -> Set Cache)
- Writes: Cache-Aside (DB -> Invalidate Cache on success) After DB commit, we invalidate cache. If invalidation fails, we log the error but don't fail the request. This ensures eventual consistency and prevents stale cache data.
- Deletes: DB -> Cache JWKDelete
func NewTieredStorage ¶
func NewTieredStorage(db Persistence, cache Cache) *TieredStorage
NewTieredStorage creates a new TieredStorage instance.
func (*TieredStorage) ClientCreate ¶ added in v0.3.0
func (s *TieredStorage) ClientCreate(ctx context.Context, metadata *ClientMetadata) (RegisteredClient, error)
func (*TieredStorage) ClientDeleteByID ¶ added in v0.3.0
func (s *TieredStorage) ClientDeleteByID(ctx context.Context, clientID BinaryUUID) error
func (*TieredStorage) ClientGetByID ¶ added in v0.3.0
func (s *TieredStorage) ClientGetByID(ctx context.Context, clientID BinaryUUID) (RegisteredClient, error)
func (*TieredStorage) ClientListAll ¶ added in v0.3.0
func (s *TieredStorage) ClientListAll(ctx context.Context, query ListQuery) ([]RegisteredClient, error)
func (*TieredStorage) ClientListByOwner ¶ added in v0.3.0
func (s *TieredStorage) ClientListByOwner(ctx context.Context, ownerID BinaryUUID, query ListQuery) ([]RegisteredClient, error)
func (*TieredStorage) ClientUpdate ¶ added in v0.3.0
func (s *TieredStorage) ClientUpdate(ctx context.Context, metadata *ClientMetadata) (RegisteredClient, error)
func (*TieredStorage) JWKDelete ¶ added in v0.3.0
func (s *TieredStorage) JWKDelete(ctx context.Context, kid string) error
func (*TieredStorage) JWKGetSigning ¶ added in v0.3.0
func (s *TieredStorage) JWKGetSigning(ctx context.Context) (string, error)
func (*TieredStorage) JWKMarkSigning ¶ added in v0.3.0
func (s *TieredStorage) JWKMarkSigning(ctx context.Context, kid string) error
func (*TieredStorage) RefreshTokenCreate ¶ added in v0.3.0
func (s *TieredStorage) RefreshTokenCreate(ctx context.Context, session *RefreshTokenSession) error
func (*TieredStorage) RefreshTokenGet ¶ added in v0.3.0
func (s *TieredStorage) RefreshTokenGet(ctx context.Context, tokenID Hash256) (*RefreshTokenSession, error)
func (*TieredStorage) RefreshTokenRevoke ¶ added in v0.3.0
func (s *TieredStorage) RefreshTokenRevoke(ctx context.Context, tokenID Hash256) error
func (*TieredStorage) RefreshTokenRevokeUser ¶ added in v0.3.0
func (s *TieredStorage) RefreshTokenRevokeUser(ctx context.Context, userID BinaryUUID) ([]Hash256, error)
func (*TieredStorage) RefreshTokenRotate ¶ added in v0.3.0
func (s *TieredStorage) RefreshTokenRotate(ctx context.Context, oldTokenID Hash256, newSession *RefreshTokenSession, gracePeriod time.Duration) error
type TokenCache ¶
type TokenCache interface {
// RefreshTokenGet 从缓存获取
RefreshTokenGet(ctx context.Context, tokenID Hash256) (*RefreshTokenSession, error)
// RefreshTokenSave 存入缓存
RefreshTokenSave(ctx context.Context, session *RefreshTokenSession, ttl time.Duration) error
// RefreshTokenRotate 令牌轮换:删除旧的,保存新的。如果保存新令牌失败,旧令牌也不应被删除(或者整个操作回滚)。
RefreshTokenRotate(ctx context.Context, oldTokenID Hash256, newSession *RefreshTokenSession, gracePeriod time.Duration) error
// RefreshTokenInvalidate 从缓存移除
RefreshTokenInvalidate(ctx context.Context, tokenID Hash256) error
// RefreshTokensInvalidate 批量从缓存移除
RefreshTokensInvalidate(ctx context.Context, tokenIDs []Hash256) error
}
TokenCache 定义了 Refresh Token 的缓存接口
type TokenRequest ¶
type TokenRequest struct {
GrantType string `form:"grant_type" json:"grant_type"`
ClientID string `form:"client_id" json:"client_id"`
ClientSecret string `form:"client_secret" json:"client_secret"`
RedirectURI string `form:"redirect_uri" json:"redirect_uri"`
// authorization_code 参数
Code string `form:"code" json:"code"`
CodeVerifier string `form:"code_verifier" json:"code_verifier"` // PKCE
// device_code 参数
DeviceCode string `form:"device_code" json:"device_code"`
// refresh_token 参数
RefreshToken string `form:"refresh_token" json:"refresh_token"`
// client_credentials 参数 (可选扩展)
Scope string `form:"scope" json:"scope"`
// password 参数 (可选扩展, 仅用于测试)
Username string `form:"username" json:"username"`
Password string `form:"password" json:"password"`
// DPoP (RFC 9449): JWK Thumbprint from DPoP proof
// 如果请求包含 DPoP header,验证后提取的 JKT
DPoPJKT string `form:"-" json:"-"` // 不从 body 绑定
}
TokenRequest 封装了 /token 端点的标准参数 对应 RFC 6749 Section 4.1.3 & 6
type TokenStorage ¶
type TokenStorage interface {
// RefreshTokenCreate 存储新的刷新令牌。
RefreshTokenCreate(ctx context.Context, session *RefreshTokenSession) error
// RefreshTokenGet 根据令牌 ID (或哈希) 查找。
// 如果未找到或过期,应返回 ErrTokenNotFound。
RefreshTokenGet(ctx context.Context, tokenID Hash256) (*RefreshTokenSession, error)
// RefreshTokenRotate 令牌轮换:删除旧的,保存新的。
// 强烈建议在事务中执行:如果保存新令牌失败,旧令牌也不应被删除(或者整个操作回滚)。
RefreshTokenRotate(ctx context.Context, oldTokenID Hash256, newSession *RefreshTokenSession, gracePeriod time.Duration) error
// RefreshTokenRevoke 撤销指定的刷新令牌。
RefreshTokenRevoke(ctx context.Context, tokenID Hash256) error
// RefreshTokenRevokeUser 撤销指定用户的所有令牌 (例如用户登出或修改密码时)。
RefreshTokenRevokeUser(ctx context.Context, userID BinaryUUID) ([]Hash256, error)
// RefreshTokenListByUser 列出指定用户的所有活跃令牌。
RefreshTokenListByUser(ctx context.Context, userID BinaryUUID) ([]*RefreshTokenSession, error)
}
TokenStorage 负责持久化刷新令牌 (Long-lived tokens)。
type TokenVerifier ¶
type TokenVerifier interface {
VerifyAccessToken(ctx context.Context, tokenStr string) (*AccessTokenClaims, error)
// ParseAccessToken 解析并验证 Token 签名和 Issuer,但不检查撤销状态。
// 用于撤销操作或需要自行处理撤销检查的场景。
ParseAccessToken(ctx context.Context, tokenStr string) (*AccessTokenClaims, error)
}
TokenVerifier 定义了 UserInfoHandler 所需的令牌验证能力。 由 Server 层实现,通常包括验签、验证 Issuer、验证过期时间、验证撤销状态。 注意:该接口不应在内部强制验证 Audience,因为 UserInfo 的 Audience 可能是动态的 ClientID。
type UserAuthenticator ¶
type UserAuthenticator interface {
// AuthenticateByPassword 根据用户名和密码进行认证。
// 成功时返回用户 ID,失败时应返回 ErrUserNotFound。
// 注意:此方法应实现速率限制和防暴力破解机制。
AuthenticateByPassword(ctx context.Context, username, password string) (BinaryUUID, string, error)
}
UserAuthenticator 定义用户认证接口。 此接口仅用于特殊场景(如负载测试的 Password Grant 流程),不应在生产环境的标准 OIDC 流程中使用。
type UserInfo ¶
type UserInfo struct {
Subject string `json:"sub"`
Name *string `json:"name,omitempty"`
GivenName *string `json:"given_name,omitempty"`
FamilyName *string `json:"family_name,omitempty"`
Nickname *string `json:"nickname,omitempty"`
PreferredUsername *string `json:"preferred_username,omitempty"`
Profile *string `json:"profile,omitempty"`
Picture *string `json:"picture,omitempty"`
Website *string `json:"website,omitempty"`
Email *string `json:"email,omitempty"`
EmailVerified *bool `json:"email_verified,omitempty"`
Gender *string `json:"gender,omitempty"`
Birthdate *string `json:"birthdate,omitempty"`
Zoneinfo *string `json:"zoneinfo,omitempty"`
Locale *string `json:"locale,omitempty"`
PhoneNumber *string `json:"phone_number,omitempty"`
PhoneNumberVerified *bool `json:"phone_number_verified,omitempty"`
UpdatedAt int64 `json:"updated_at,omitempty"`
// Metadata 存储扩展字段 (Custom Claims)。
// json:"-" 表示标准库忽略该字段,我们将在 MarshalJSON 中手动将其合并到顶层。
Metadata map[string]interface{} `json:"-"`
}
UserInfo 表示 OIDC UserInfo 端点的标准响应结构。 参见: OIDC Core 1.0, Section 5.1.
func GetUserInfo ¶
func GetUserInfo(ctx context.Context, storage UserInfoGetter, verifier TokenVerifier, claims *AccessTokenClaims) (*UserInfo, error)
GetUserInfo 根据 claims 获取用户信息
func (*UserInfo) MarshalJSON ¶ added in v0.3.0
MarshalJSON 自定义序列化逻辑
func (*UserInfo) UnmarshalJSON ¶ added in v0.3.0
UnmarshalJSON 自定义反序列化逻辑
type UserInfoGetter ¶
type UserInfoGetter interface {
// 测试中需要添加可查询的用户信息
UserCreateInfo(ctx context.Context, userInfo *UserInfo) error
// UserGetInfoByID 根据 UserID 和请求的 Scopes 返回用户信息。
// scope 参数允许实现层根据权限过滤返回字段 (例如:没有 'email' scope 就不查邮箱)。
UserGetInfoByID(ctx context.Context, userID BinaryUUID, scopes []string) (*UserInfo, error)
}
UserInfoGetter 用于从业务系统获取用户信息,以填充 ID Token 或响应 UserInfo 端点。
Source Files
¶
- authorize.go
- claims.go
- device_flow.go
- discovery.go
- dpop.go
- dpop_middleware.go
- dpop_time.go
- errors.go
- exchange.go
- gc_worker.go
- index.go
- interfaces.go
- introspection.go
- issuer.go
- jwks.go
- key.go
- key_manager.go
- key_provider.go
- key_rotation.go
- metrics.go
- par.go
- password_stub.go
- pkce.go
- registration.go
- revocation.go
- secret.go
- server.go
- server_lifecycle.go
- session.go
- storage.go
- types.go
- userinfo.go
- utils.go
- verifier.go