Documentation
¶
Index ¶
- Constants
- Variables
- func ComputeCodeChallenge(verifier string) string
- func ComputeLeftHash(value string) string
- func Decrypt(encodedCiphertext string, key []byte) ([]byte, error)
- func DeriveAESKey(secret string) []byte
- func DerivePairwiseSubject(pairwiseSecret, sectorIdentifier, userID string) string
- func Encrypt(plaintext []byte, key []byte) (string, error)
- func GenerateRandomString(byteLen int) (string, error)
- func HashSecret(secret string) string
- func HashToken(token string) string
- func SignOAuthQuery(query, secret string) string
- func VerifyOAuthQuery(query, signature, secret string) bool
- func VerifyPKCE(verifier, challenge, method string) bool
- type AccessTokenType
- type AuthorizeFailedEventPayload
- type AuthorizeParams
- type AuthorizeResult
- type AuthorizeSuccessEventPayload
- type ClientEventPayload
- type ClientType
- type Config
- type ConsentEventPayload
- type ConsentParams
- type ConsentResult
- type ContinueAuthorizeParams
- type CustomClaimsFunc
- type DeleteClientParams
- type DeleteClientResult
- type EndSessionParams
- type EndSessionResult
- type GetClientParams
- type GetClientResult
- type GrantType
- type HMACSigner
- type IntrospectParams
- type IntrospectResult
- type JWTSigner
- type ListConsentsParams
- type ListConsentsResult
- type OAuthAccessToken
- type OAuthAuthorizationCode
- type OAuthClient
- type OAuthConsent
- type OAuthMetadataParams
- type OAuthMetadataResult
- type OAuthRefreshToken
- type OpenIDConfigurationParams
- type OpenIDConfigurationResult
- type Option
- func WithAccessTokenType(t AccessTokenType) Option
- func WithCustomAccessTokenClaims(fn CustomClaimsFunc) Option
- func WithCustomIDTokenClaims(fn CustomClaimsFunc) Option
- func WithCustomUserInfoClaims(fn CustomClaimsFunc) Option
- func WithDynamicClientRegistration(allow, allowUnauthenticated bool) Option
- func WithGrantTypes(types ...GrantType) Option
- func WithIssuer(issuer string) Option
- func WithJWTSigner(signer JWTSigner) Option
- func WithPages(loginPage, consentPage string) Option
- func WithPairwiseSecret(secret string) Option
- func WithScopes(scopes ...string) Option
- func WithStoreModes(secretMode, tokenMode StoreMode, secretKey string) Option
- func WithTokenExpirations(code, access, refresh, idToken time.Duration) Option
- type Plugin
- func (p *Plugin) Authorize(ctx context.Context, params AuthorizeParams) (*AuthorizeResult, error)
- func (p *Plugin) Config() Config
- func (p *Plugin) Consent(ctx context.Context, params ConsentParams) (*ConsentResult, error)
- func (p *Plugin) ContinueAuthorize(ctx context.Context, params ContinueAuthorizeParams) (*AuthorizeResult, error)
- func (p *Plugin) DeleteClient(ctx context.Context, params DeleteClientParams) (*DeleteClientResult, error)
- func (p *Plugin) EndSession(ctx context.Context, params EndSessionParams) (*EndSessionResult, error)
- func (p *Plugin) GetClient(ctx context.Context, params GetClientParams) (*GetClientResult, error)
- func (p *Plugin) GetOAuthAuthorizationServerMetadata(ctx context.Context, params OAuthMetadataParams) (*OAuthMetadataResult, error)
- func (p *Plugin) GetOpenIDConfiguration(ctx context.Context, params OpenIDConfigurationParams) (*OpenIDConfigurationResult, error)
- func (p *Plugin) ID() string
- func (p *Plugin) Init(ctx *plugin.Context) error
- func (p *Plugin) Introspect(ctx context.Context, params IntrospectParams) (*IntrospectResult, error)
- func (p *Plugin) ListConsents(ctx context.Context, params ListConsentsParams) (*ListConsentsResult, error)
- func (p *Plugin) RegisterClient(ctx context.Context, params RegisterClientParams) (*RegisterClientResult, error)
- func (p *Plugin) Repository() Repository
- func (p *Plugin) RequireScope(requiredScopes ...string) func(next http.Handler) http.Handler
- func (p *Plugin) Revoke(ctx context.Context, params RevokeParams) (*RevokeResult, error)
- func (p *Plugin) RevokeConsent(ctx context.Context, params RevokeConsentParams) (*RevokeConsentResult, error)
- func (p *Plugin) RotateClientSecret(ctx context.Context, params RotateClientSecretParams) (*RotateClientSecretResult, error)
- func (p *Plugin) Token(ctx context.Context, params TokenParams) (*TokenResult, error)
- func (p *Plugin) UpdateClient(ctx context.Context, params UpdateClientParams) (*UpdateClientResult, error)
- func (p *Plugin) UserInfo(ctx context.Context, params UserInfoParams) (*UserInfoResult, error)
- type RegisterClientParams
- type RegisterClientResult
- type Repository
- type ResponseType
- type RevokeConsentParams
- type RevokeConsentResult
- type RevokeParams
- type RevokeResult
- type RotateClientSecretParams
- type RotateClientSecretResult
- type SessionEndedEventPayload
- type StoreMode
- type SubjectType
- type TokenEndpointAuthMethod
- type TokenIssuedEventPayload
- type TokenParams
- type TokenRefreshedEventPayload
- type TokenResult
- type TokenRevokedEventPayload
- type UpdateClientParams
- type UpdateClientResult
- type UserInfoParams
- type UserInfoResult
Constants ¶
const ( // EventClientCreated is dispatched when a new OAuth client is registered. EventClientCreated = "oauth2:client:created" // EventClientUpdated is dispatched when an existing OAuth client is updated. EventClientUpdated = "oauth2:client:updated" // EventClientDeleted is dispatched when an OAuth client is deleted. EventClientDeleted = "oauth2:client:deleted" // EventAuthorizeSuccess is dispatched when an authorization request successfully issues an authorization code. EventAuthorizeSuccess = "oauth2:authorize:success" // EventAuthorizeFailed is dispatched when an authorization request fails validation or is rejected. EventAuthorizeFailed = "oauth2:authorize:failed" // EventTokenIssued is dispatched when an access token, refresh token, or ID token is issued. EventTokenIssued = "oauth2:token:issued" // EventTokenRefreshed is dispatched when a refresh token exchange succeeds with token rotation. EventTokenRefreshed = "oauth2:token:refreshed" // EventTokenRevoked is dispatched when an access token or refresh token is explicitly revoked. EventTokenRevoked = "oauth2:token:revoked" // EventConsentGranted is dispatched when an end-user approves requested scopes for a client. EventConsentGranted = "oauth2:consent:granted" // EventConsentRevoked is dispatched when an end-user revokes previously granted scopes for a client. EventConsentRevoked = "oauth2:consent:revoked" // EventSessionEnded is dispatched when an RP-Initiated Logout flow completes. EventSessionEnded = "oauth2:session:ended" )
Event topic constants dispatched on the shared plugin.Context EventBus.
const ( // ScopeOpenID requests an OpenID Connect ID Token and enables identity workflows. ScopeOpenID = "openid" // ScopeProfile grants access to the End-User's default Profile Claims (name, picture, etc.). ScopeProfile = "profile" // ScopeEmail grants access to the email and email_verified claims. ScopeEmail = "email" // ScopeOffline requests issuance of an OAuth 2.1 Refresh Token (offline_access). ScopeOffline = "offline_access" // ScopePhone grants access to phone_number and phone_number_verified claims. ScopePhone = "phone" // ScopeAddress grants access to the address claim. ScopeAddress = "address" )
Standard OpenID Connect (OIDC Core 1.0) and OAuth 2.1 Scope Constants.
const ( // PromptNone instructs the server not to display any authentication or consent UI. PromptNone = "none" // PromptLogin forces the server to prompt the user for re-authentication. PromptLogin = "login" // PromptConsent forces the server to prompt the user for consent. PromptConsent = "consent" // PromptSelectAccount prompts the user to select a user account. PromptSelectAccount = "select_account" )
Prompt types for OpenID Connect authorization requests.
const ( // CodeChallengeMethodS256 represents SHA-256 hashed code challenge (mandatory in OAuth 2.1). CodeChallengeMethodS256 = "S256" // CodeChallengeMethodPlain represents plain text challenge (deprecated and forbidden in OAuth 2.1). CodeChallengeMethodPlain = "plain" )
CodeChallengeMethod constants for PKCE (RFC 7636).
const ( ExtraKeyClientID = "oauth2:client_id" ExtraKeyClientSecret = "oauth2:client_secret" ExtraKeyUserID = "oauth2:user_id" ExtraKeySessionID = "oauth2:session_id" ExtraKeyScopes = "oauth2:scopes" ExtraKeyRedirectURI = "oauth2:redirect_uri" ExtraKeyCodeChallenge = "oauth2:code_challenge" ExtraKeyNonce = "oauth2:nonce" ExtraKeyResource = "oauth2:resource" ExtraKeyClaims = "oauth2:claims" ExtraKeyAccessToken = "oauth2:access_token" ExtraKeyRefreshToken = "oauth2:refresh_token" ExtraKeyIDToken = "oauth2:id_token" ExtraKeyAuthTime = "oauth2:auth_time" ExtraKeyTokenType = "oauth2:token_type" ExtraKeyFamilyID = "oauth2:family_id" ExtraKeyInteractiveQuery = "oauth2:interactive_query" )
Dynamic metadata keys used across Extra map bags and event payloads.
const ( ContextKeyOAuthClient = "oauth2:current_client" ContextKeyOAuthToken = "oauth2:current_token" ContextKeyOAuthUser = "oauth2:current_user" ContextKeyOAuthAuthCode = "oauth2:current_auth_code" ContextKeyOAuthRefreshToken = "oauth2:current_refresh_token" )
ContextKey constants for storing and retrieving OAuth 2.1 objects in plugin.Context.
const PluginID = "oauth2"
PluginID is the unique string identifier for the OAuth 2.1 Provider plugin ("oauth2").
const (
TokenIntrospectContextKey contextKey = "oauth2_token_introspect"
)
Variables ¶
var ( // ErrDecryptionFailed is returned when ciphertext fails authenticated AES-GCM decryption or authentication tag check. ErrDecryptionFailed = errors.New("oauth2/crypto: decryption failed or invalid authentication tag") // ErrInvalidKeyLength is returned when a symmetric encryption key does not meet requirements. ErrInvalidKeyLength = errors.New("oauth2/crypto: invalid key length (expected 32 bytes for AES-256)") )
var ( // ErrClientNotFound is returned when an OAuth client cannot be found in storage. ErrClientNotFound = errors.New("oauth2: client not found") // ErrClientDisabled is returned when an OAuth client has been administratively disabled. ErrClientDisabled = errors.New("oauth2: client is disabled") // ErrInvalidClient is returned when client credentials (ID or secret) are invalid or mismatched. ErrInvalidClient = errors.New("oauth2: invalid client credentials") // ErrInvalidClientSecret is returned when the provided client secret does not match the stored secret. ErrInvalidClientSecret = errors.New("oauth2: invalid client secret") // ErrInvalidRedirectURI is returned when the redirect_uri does not match any registered URI for the client. ErrInvalidRedirectURI = errors.New("oauth2: invalid or unregistered redirect_uri") // ErrInvalidResponseType is returned when response_type is not supported (OAuth 2.1 requires 'code'). ErrInvalidResponseType = errors.New("oauth2: unsupported response_type (must be 'code')") // ErrInvalidGrantType is returned when grant_type is unsupported or not permitted for the client. ErrInvalidGrantType = errors.New("oauth2: unsupported or unauthorized grant_type") // ErrInvalidAuthorizationCode is returned when the authorization code is invalid, already consumed, or not found. ErrInvalidAuthorizationCode = errors.New("oauth2: invalid or already consumed authorization code") // ErrAuthorizationCodeExpired is returned when the authorization code has exceeded its validity lifetime. ErrAuthorizationCodeExpired = errors.New("oauth2: authorization code has expired") // ErrInvalidPKCE is returned when code_verifier is missing or fails SHA-256 S256 comparison against code_challenge. ErrInvalidPKCE = errors.New("oauth2: invalid code_verifier or failed PKCE verification") // ErrInvalidCodeChallengeMethod is returned when code_challenge_method is not 'S256' (OAuth 2.1 disallows 'plain'). ErrInvalidCodeChallengeMethod = errors.New("oauth2: only 'S256' code_challenge_method is supported in OAuth 2.1") // ErrInvalidRefreshToken is returned when a refresh token cannot be found or is expired. ErrInvalidRefreshToken = errors.New("oauth2: invalid or expired refresh token") // ErrRefreshTokenRevoked is returned when an already revoked refresh token is presented (potential token theft). ErrRefreshTokenRevoked = errors.New("oauth2: refresh token has been revoked") // ErrInvalidAccessToken is returned when an access token cannot be validated or is expired/revoked. ErrInvalidAccessToken = errors.New("oauth2: invalid or expired access token") // ErrConsentRequired is returned in prompt=none when the user has not pre-consented to the requested scopes. ErrConsentRequired = errors.New("oauth2: consent required") // ErrLoginRequired is returned in prompt=none when the user is not actively authenticated. ErrLoginRequired = errors.New("oauth2: login required") // ErrAccessDenied is returned when the resource owner or authorization server denied the request. ErrAccessDenied = errors.New("oauth2: access denied") // ErrInvalidScope is returned when the requested scope is malformed or exceeds authorized client scopes. ErrInvalidScope = errors.New("oauth2: requested scope is invalid or exceeds client permissions") // ErrInvalidRequest is returned when required parameters are missing or malformed. ErrInvalidRequest = errors.New("oauth2: invalid request parameters") ErrUnauthorizedClient = errors.New("oauth2: client is not authorized to use this grant type") // ErrDynamicRegistrationDisabled is returned when dynamic client registration is disabled by configuration. ErrDynamicRegistrationDisabled = errors.New("oauth2: dynamic client registration is disabled") // ErrInvalidSignature is returned when an HMAC query signature on interactive redirects fails verification. ErrInvalidSignature = errors.New("oauth2: invalid interactive query signature") )
Sentinel error definitions for OAuth 2.1 and OpenID Connect flows.
var ( // ErrInvalidJWT is returned when a JWT token is malformed, has invalid signature or has expired. ErrInvalidJWT = errors.New("oauth2/signer: invalid JWT token") // ErrJWTExpired is returned when a JWT token's 'exp' claim is in the past. ErrJWTExpired = errors.New("oauth2/signer: JWT token has expired") )
Functions ¶
func ComputeCodeChallenge ¶
ComputeCodeChallenge computes the PKCE S256 code challenge for a given code verifier.
OAuth 2.1 RFC 7636 Section 4.2 specifies:
code_challenge = BASE64URL-ENCODE(SHA256(ASCII(code_verifier)))
func ComputeLeftHash ¶
ComputeLeftHash computes the OIDC at_hash or c_hash claim value for ID Tokens (RFC 7636 / OIDC Core 1.0).
It takes the first 128 bits (16 bytes) of the SHA-256 hash and encodes it in Base64URL without padding.
func DeriveAESKey ¶
DeriveAESKey derives a 32-byte cryptographic key for AES-256 from an arbitrary secret string.
func DerivePairwiseSubject ¶
DerivePairwiseSubject generates a deterministic pseudonymous subject identifier (sub claim) for a user given a sector identifier (or client redirect host) and pairwise secret.
OIDC Core 1.0 Section 8.1:
sub = HMAC-SHA256(pairwiseSecret, sector_identifier + ":" + user_id)
func Encrypt ¶
Encrypt encrypts plain text data using AES-256-GCM authenticated encryption.
It generates a cryptographically random 12-byte nonce and returns the concatenated nonce + ciphertext + GCM auth tag encoded in Base64URL without padding.
func GenerateRandomString ¶
GenerateRandomString generates a cryptographically secure random string of specified byte length, encoded in Base64URL without padding.
func HashSecret ¶
HashSecret computes a deterministic SHA-256 hash string for a client secret.
func HashToken ¶
HashToken computes a deterministic SHA-256 hash string for an access token or refresh token.
func SignOAuthQuery ¶
SignOAuthQuery calculates an HMAC-SHA256 signature for interactive query parameters.
func VerifyOAuthQuery ¶
VerifyOAuthQuery verifies the HMAC-SHA256 signature of an interactive query string.
func VerifyPKCE ¶
VerifyPKCE validates an incoming code verifier against a stored code challenge and method.
In strict OAuth 2.1 mode, only the "S256" challenge method is permitted. Comparison is performed using constant-time comparison to prevent timing attacks.
Types ¶
type AccessTokenType ¶
type AccessTokenType string
AccessTokenType defines the format of the issued Access Token.
const ( // AccessTokenTypeJWT issues structured and signed JSON Web Tokens per RFC 9068. AccessTokenTypeJWT AccessTokenType = "jwt" // AccessTokenTypeOpaque issues cryptographically random opaque tokens persisted in storage. AccessTokenTypeOpaque AccessTokenType = "opaque" )
type AuthorizeFailedEventPayload ¶
type AuthorizeFailedEventPayload struct {
// ClientID is the client ID involved in the failed request, if known.
ClientID string `json:"client_id,omitempty"`
// Error is the error description of the failure.
Error string `json:"error"`
// RedirectURI is the callback URI if available for error redirection.
RedirectURI string `json:"redirect_uri,omitempty"`
// Timestamp is the moment the failure occurred.
Timestamp time.Time `json:"timestamp"`
}
AuthorizeFailedEventPayload represents the payload dispatched when an authorization request fails.
type AuthorizeParams ¶
type AuthorizeParams struct {
ClientID string `json:"client_id"`
RedirectURI string `json:"redirect_uri"`
ResponseType string `json:"response_type"`
CodeChallenge string `json:"code_challenge"`
CodeChallengeMethod string `json:"code_challenge_method"`
Scope string `json:"scope"`
State string `json:"state"`
Nonce string `json:"nonce,omitempty"`
Prompt string `json:"prompt,omitempty"`
Resource string `json:"resource,omitempty"`
SessionID string `json:"session_id,omitempty"`
UserID string `json:"user_id,omitempty"`
plugin.ExtraContainer
}
AuthorizeParams defines input parameters for initiating the OAuth 2.1 authorization code flow.
type AuthorizeResult ¶
type AuthorizeResult struct {
RedirectURI string `json:"redirect_uri"`
Code string `json:"code,omitempty"`
State string `json:"state,omitempty"`
Issuer string `json:"iss,omitempty"`
IsRedirect bool `json:"is_redirect"`
NeedsLogin bool `json:"needs_login"`
NeedsConsent bool `json:"needs_consent"`
}
AuthorizeResult represents the outcome of an authorization request.
type AuthorizeSuccessEventPayload ¶
type AuthorizeSuccessEventPayload struct {
// ClientID is the client ID that received the authorization code.
ClientID string `json:"client_id"`
// UserID is the authenticated user ID granting authorization.
UserID string `json:"user_id"`
// RedirectURI is the validated callback redirect URI.
RedirectURI string `json:"redirect_uri"`
// Scopes is the list of granted scopes.
Scopes []string `json:"scopes"`
// Code is the issued authorization code string.
Code string `json:"code"`
// Timestamp is the moment the code was issued.
Timestamp time.Time `json:"timestamp"`
}
AuthorizeSuccessEventPayload represents the payload dispatched upon successful authorization code issuance.
type ClientEventPayload ¶
type ClientEventPayload struct {
// Client is the OAuth client entity created, updated, or deleted.
Client *OAuthClient `json:"client"`
// Timestamp is the moment the event occurred.
Timestamp time.Time `json:"timestamp"`
}
ClientEventPayload represents the payload dispatched for client lifecycle events.
type ClientType ¶
type ClientType string
ClientType defines the category of OAuth client.
const ( // ClientTypeConfidential represents confidential clients capable of securely storing credentials (e.g. backend servers). ClientTypeConfidential ClientType = "confidential" // ClientTypePublic represents public clients unable to securely store secrets (e.g. SPAs, mobile apps). ClientTypePublic ClientType = "public" )
type Config ¶
type Config struct {
// Issuer is the base URL of the authorization server ("iss" claim in tokens and discovery).
Issuer string
// LoginPage is the relative or absolute path of the user login UI page for interactive redirection.
LoginPage string
// ConsentPage is the relative or absolute path of the user consent UI page for interactive redirection.
ConsentPage string
// Scopes is the list of supported scopes announced by the authorization server.
Scopes []string
// GrantTypes is the list of OAuth 2.1 grant types enabled on this server.
GrantTypes []GrantType
// AccessTokenType specifies whether Access Tokens are issued as RFC 9068 JWTs or opaque tokens.
AccessTokenType AccessTokenType
// CodeExpiresIn is the validity duration of single-use authorization codes (default: 10m).
CodeExpiresIn time.Duration
// AccessTokenExpiresIn is the validity duration of user access tokens (default: 1h).
AccessTokenExpiresIn time.Duration
// RefreshTokenExpiresIn is the validity duration of refresh tokens (default: 30 days).
RefreshTokenExpiresIn time.Duration
// IDTokenExpiresIn is the validity duration of OpenID Connect ID Tokens (default: 1h).
IDTokenExpiresIn time.Duration
// M2MAccessTokenExpiresIn is the validity duration of client_credentials access tokens (default: 2h).
M2MAccessTokenExpiresIn time.Duration
// AllowDynamicClientRegistration enables RFC 7591 Dynamic Client Registration endpoint.
AllowDynamicClientRegistration bool
// AllowUnauthenticatedClientRegistration allows client registration without an initial access token.
AllowUnauthenticatedClientRegistration bool
// StoreClientSecretMode defines how client secrets are persisted ("plain", "hashed", "encrypted").
StoreClientSecretMode StoreMode
// StoreTokensMode defines how tokens are persisted ("plain", "hashed", "encrypted").
StoreTokensMode StoreMode
// SecretKey is the master cryptographic key used for symmetric AES-256-GCM encryption and HMAC query signing.
SecretKey string
// PairwiseSecret is the cryptographic salt used to compute pairwise pseudonymous subjects.
PairwiseSecret string
// ValidAudiences is the list of accepted audiences for validation.
ValidAudiences []string
// JWTSigner is the custom or default token signer used to sign ID Tokens and JWT Access Tokens.
JWTSigner JWTSigner
// CustomAccessTokenClaims is an optional callback to enrich JWT Access Tokens with application-specific claims.
CustomAccessTokenClaims CustomClaimsFunc
// CustomIDTokenClaims is an optional callback to enrich OIDC ID Tokens with application-specific claims.
CustomIDTokenClaims CustomClaimsFunc
// CustomUserInfoClaims is an optional callback to enrich OIDC /userinfo endpoint responses.
CustomUserInfoClaims CustomClaimsFunc
}
Config defines the configuration options for the OAuth 2.1 and OpenID Connect Provider plugin.
func DefaultConfig ¶
func DefaultConfig() Config
DefaultConfig returns the recommended production defaults for OAuth 2.1 and OpenID Connect.
type ConsentEventPayload ¶
type ConsentEventPayload struct {
// Consent is the consent record granted or revoked.
Consent *OAuthConsent `json:"consent"`
// Timestamp is the moment the consent event occurred.
Timestamp time.Time `json:"timestamp"`
}
ConsentEventPayload represents the payload dispatched for user consent events.
type ConsentParams ¶
type ConsentParams struct {
OAuthQuery string `json:"oauth_query"`
OAuthSignature string `json:"oauth_signature"`
UserID string `json:"user_id"`
ApprovedScopes []string `json:"approved_scopes"`
Denied bool `json:"denied"`
plugin.ExtraContainer
}
ConsentParams defines input parameters for user approval or denial of requested scopes.
type ConsentResult ¶
type ConsentResult struct {
RedirectURI string `json:"redirect_uri"`
Code string `json:"code,omitempty"`
State string `json:"state,omitempty"`
Issuer string `json:"iss,omitempty"`
}
ConsentResult represents the result of processing user consent.
type ContinueAuthorizeParams ¶
type ContinueAuthorizeParams struct {
OAuthQuery string `json:"oauth_query"`
OAuthSignature string `json:"oauth_signature"`
SessionID string `json:"session_id"`
UserID string `json:"user_id"`
plugin.ExtraContainer
}
ContinueAuthorizeParams defines input parameters when resuming authorization after login/consent.
type CustomClaimsFunc ¶
type CustomClaimsFunc func(ctx context.Context, client *OAuthClient, user *entity.User, scopes []string) (map[string]any, error)
CustomClaimsFunc allows injecting additional custom claims into tokens or UserInfo responses.
type DeleteClientParams ¶
type DeleteClientParams struct {
ClientID string `json:"client_id"`
plugin.ExtraContainer
}
DeleteClientParams defines input parameters to delete an OAuth client.
type DeleteClientResult ¶
type DeleteClientResult struct {
Success bool `json:"success"`
}
DeleteClientResult reports the outcome of deleting a client.
type EndSessionParams ¶
type EndSessionParams struct {
IDTokenHint string `json:"id_token_hint,omitempty"`
ClientID string `json:"client_id,omitempty"`
PostLogoutRedirectURI string `json:"post_logout_redirect_uri,omitempty"`
State string `json:"state,omitempty"`
SessionID string `json:"session_id,omitempty"`
plugin.ExtraContainer
}
EndSessionParams defines input parameters for RP-Initiated Logout.
type EndSessionResult ¶
type EndSessionResult struct {
RedirectURI string `json:"redirect_uri"`
}
EndSessionResult contains the redirection target after logout.
type GetClientParams ¶
type GetClientParams struct {
ClientID string `json:"client_id"`
plugin.ExtraContainer
}
GetClientParams defines input parameters to lookup an OAuth client.
type GetClientResult ¶
type GetClientResult struct {
Client *OAuthClient `json:"client"`
}
GetClientResult contains the client entity.
type GrantType ¶
type GrantType string
GrantType represents the authorization grant types defined in OAuth 2.1.
const ( // GrantTypeAuthorizationCode represents the authorization code grant type (RFC 6749 / OAuth 2.1). GrantTypeAuthorizationCode GrantType = "authorization_code" // GrantTypeClientCredentials represents machine-to-machine client credentials grant type. GrantTypeClientCredentials GrantType = "client_credentials" // GrantTypeRefreshToken represents the refresh token grant type with mandatory rotation. GrantTypeRefreshToken GrantType = "refresh_token" )
type HMACSigner ¶
type HMACSigner struct {
// contains filtered or unexported fields
}
HMACSigner is a lightweight, RFC 7519 compliant HMAC-SHA256 JWT signer.
func NewHMACSigner ¶
func NewHMACSigner(secret string, keyID ...string) *HMACSigner
NewHMACSigner creates a new HMAC-SHA256 JWTSigner with the specified secret and optional key ID.
type IntrospectParams ¶
type IntrospectParams struct {
Token string `json:"token"`
TokenTypeHint string `json:"token_type_hint,omitempty"`
ClientID string `json:"client_id,omitempty"`
ClientSecret string `json:"client_secret,omitempty"`
plugin.ExtraContainer
}
IntrospectParams defines input parameters for token introspection (RFC 7662).
type IntrospectResult ¶
type IntrospectResult 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"`
Extra map[string]any `json:"extra,omitempty"`
}
IntrospectResult represents the introspection metadata (RFC 7662).
type JWTSigner ¶
type JWTSigner interface {
// Sign signs the given claims map with the configured algorithm and lifetime.
Sign(ctx context.Context, claims map[string]any, expiresIn time.Duration) (tokenString string, keyID string, err error)
// Verify validates the JWT signature, integrity, and expiration, returning verified claims.
Verify(ctx context.Context, tokenString string) (claims map[string]any, err error)
}
JWTSigner defines the contract for signing and verifying JWT tokens (ID Tokens and RFC 9068 Access Tokens).
type ListConsentsParams ¶
type ListConsentsParams struct {
UserID string `json:"user_id"`
plugin.ExtraContainer
}
ListConsentsParams defines input parameters to list user consents.
type ListConsentsResult ¶
type ListConsentsResult struct {
Consents []*OAuthConsent `json:"consents"`
}
ListConsentsResult contains the list of active user consents.
type OAuthAccessToken ¶
type OAuthAccessToken struct {
// ID is the internal unique identifier of the access token record.
ID string `json:"id"`
// Token is the SHA-256 hash or encrypted representation of the access token string.
Token string `json:"token"`
// ClientID is the client application that received this token.
ClientID string `json:"client_id"`
// UserID is the authenticated user ID (nil for machine-to-machine client credentials).
UserID *string `json:"user_id,omitempty"`
// SessionID is the optional session ID tied to this token.
SessionID *string `json:"session_id,omitempty"`
// RefreshID is the optional ID of the parent refresh token that spawned this access token.
RefreshID *string `json:"refresh_id,omitempty"`
// ReferenceID is an optional external identifier.
ReferenceID *string `json:"reference_id,omitempty"`
// Scopes is the list of granted scopes authorized by this token.
Scopes []string `json:"scopes"`
// ExpiresAt is the timestamp when the access token expires.
ExpiresAt time.Time `json:"expires_at"`
// CreatedAt is the timestamp when the access token was issued.
CreatedAt time.Time `json:"created_at"`
}
OAuthAccessToken represents an issued access token (stored for opaque tokens or introspection).
type OAuthAuthorizationCode ¶
type OAuthAuthorizationCode struct {
// ID is the internal unique identifier of the authorization code record.
ID string `json:"id"`
// Code is the raw or hashed authorization code string.
Code string `json:"code"`
// ClientID is the client application that requested the authorization code.
ClientID string `json:"client_id"`
// UserID is the authenticated user ID granting authorization.
UserID string `json:"user_id"`
// SessionID is the active user session ID at the time of authorization.
SessionID string `json:"session_id"`
// RedirectURI is the redirect URI verified and locked during the authorization step.
RedirectURI string `json:"redirect_uri"`
// CodeChallenge is the Base64URL-encoded SHA-256 PKCE challenge (RFC 7636).
CodeChallenge string `json:"code_challenge"`
// CodeChallengeMethod is the PKCE transform method (always "S256" in OAuth 2.1).
CodeChallengeMethod string `json:"code_challenge_method"`
// Scopes is the list of granted scopes associated with this authorization code.
Scopes []string `json:"scopes"`
// Nonce is an optional string value used to associate a client session with an ID Token (OIDC).
Nonce string `json:"nonce,omitempty"`
// Resource is an optional target resource indicator (RFC 8707).
Resource string `json:"resource,omitempty"`
// ExpiresAt is the timestamp after which this authorization code is invalid (default: 10m).
ExpiresAt time.Time `json:"expires_at"`
// CreatedAt is the timestamp when the authorization code was issued.
CreatedAt time.Time `json:"created_at"`
}
OAuthAuthorizationCode represents a single-use authorization code issued during the authorization code flow.
type OAuthClient ¶
type OAuthClient struct {
// ID is the internal unique identifier of the client record in the database.
ID string `json:"id"`
// ClientID is the unique public client identifier used in OAuth requests.
ClientID string `json:"client_id"`
// ClientSecret is the hashed or encrypted client secret (nil for public clients).
ClientSecret *string `json:"client_secret,omitempty"`
// ClientSecretExpiresAt is the expiration timestamp for the client secret, if applicable.
ClientSecretExpiresAt *time.Time `json:"client_secret_expires_at,omitempty"`
// Name is the human-readable display name of the client application.
Name string `json:"name"`
// URI is the home page URL of the client application.
URI string `json:"uri,omitempty"`
// Icon is the URL of the client application logo or icon.
Icon string `json:"icon,omitempty"`
// Contacts is a list of contact email addresses for the client application.
Contacts []string `json:"contacts,omitempty"`
// TOS is the Terms of Service URL for the client application.
TOS string `json:"tos,omitempty"`
// Policy is the Privacy Policy URL for the client application.
Policy string `json:"policy,omitempty"`
// SoftwareID is an identifier assigned by the client developer (RFC 7591).
SoftwareID string `json:"software_id,omitempty"`
// SoftwareVersion is a version identifier assigned by the client developer (RFC 7591).
SoftwareVersion string `json:"software_version,omitempty"`
// SoftwareStatement is a signed software statement JWT (RFC 7591).
SoftwareStatement string `json:"software_statement,omitempty"`
// RedirectURIs is the list of authorized callback redirect URIs for this client.
RedirectURIs []string `json:"redirect_uris"`
// PostLogoutRedirectURIs is the list of allowed post-logout redirect URIs (RP-Initiated Logout).
PostLogoutRedirectURIs []string `json:"post_logout_redirect_uris,omitempty"`
// TokenEndpointAuthMethod specifies the authentication method used at the token endpoint ("client_secret_basic", "client_secret_post", "none").
TokenEndpointAuthMethod TokenEndpointAuthMethod `json:"token_endpoint_auth_method"`
// GrantTypes is the list of OAuth 2.1 grant types allowed for this client ("authorization_code", "client_credentials", "refresh_token").
GrantTypes []GrantType `json:"grant_types"`
// ResponseTypes is the list of response types allowed for this client (typically ["code"]).
ResponseTypes []ResponseType `json:"response_types"`
// Scopes is the list of authorized scopes the client may request.
Scopes []string `json:"scopes,omitempty"`
// Public indicates if the client is a public client (e.g. SPA, mobile) incapable of protecting secrets.
Public bool `json:"public"`
// Type specifies the client category (e.g., "confidential", "public").
Type ClientType `json:"type,omitempty"`
// RequirePKCE enforces PKCE code challenge verification (defaults to true in OAuth 2.1).
RequirePKCE bool `json:"require_pkce"`
// SubjectType specifies the subject identifier type for OIDC ("public" or "pairwise").
SubjectType SubjectType `json:"subject_type,omitempty"`
// SkipConsent indicates if the user consent prompt can be bypassed for trusted first-party clients.
SkipConsent bool `json:"skip_consent"`
// EnableEndSession allows this client to trigger RP-Initiated Logout (OIDC End Session).
EnableEndSession bool `json:"enable_end_session"`
// Disabled indicates if the client has been administratively disabled.
Disabled bool `json:"disabled"`
// UserID is the optional ID of the user who registered/owns this client.
UserID *string `json:"user_id,omitempty"`
// ReferenceID is an optional external identifier for multi-tenant or organization mapping.
ReferenceID *string `json:"reference_id,omitempty"`
// Metadata holds arbitrary custom properties and client configuration.
Metadata map[string]any `json:"metadata,omitempty"`
// CreatedAt is the timestamp when the client record was created.
CreatedAt time.Time `json:"created_at"`
// UpdatedAt is the timestamp when the client record was last updated.
UpdatedAt time.Time `json:"updated_at"`
}
OAuthClient represents a registered OAuth 2.1 / OpenID Connect client application.
type OAuthConsent ¶
type OAuthConsent struct {
// ID is the internal unique identifier of the consent record.
ID string `json:"id"`
// ClientID is the client application identifier.
ClientID string `json:"client_id"`
// UserID is the user ID who granted the consent.
UserID string `json:"user_id"`
// ReferenceID is an optional external identifier.
ReferenceID *string `json:"reference_id,omitempty"`
// Scopes is the list of scopes approved by the user.
Scopes []string `json:"scopes"`
// CreatedAt is the timestamp when consent was first granted.
CreatedAt time.Time `json:"created_at"`
// UpdatedAt is the timestamp when consent was last modified.
UpdatedAt time.Time `json:"updated_at"`
}
OAuthConsent represents explicit consent granted by an end-user to a client application for a set of scopes.
type OAuthMetadataParams ¶
type OAuthMetadataParams struct {
plugin.ExtraContainer
}
OAuthMetadataParams defines input parameters for RFC 8414 metadata.
type OAuthMetadataResult ¶
type OAuthMetadataResult struct {
Issuer string `json:"issuer"`
AuthorizationEndpoint string `json:"authorization_endpoint"`
TokenEndpoint string `json:"token_endpoint"`
IntrospectionEndpoint string `json:"introspection_endpoint"`
RevocationEndpoint string `json:"revocation_endpoint"`
RegistrationEndpoint string `json:"registration_endpoint,omitempty"`
ResponseTypesSupported []string `json:"response_types_supported"`
GrantTypesSupported []string `json:"grant_types_supported"`
CodeChallengeMethodsSupported []string `json:"code_challenge_methods_supported"`
TokenEndpointAuthMethodsSupported []string `json:"token_endpoint_auth_methods_supported"`
ScopesSupported []string `json:"scopes_supported"`
}
OAuthMetadataResult represents Authorization Server Metadata (RFC 8414).
type OAuthRefreshToken ¶
type OAuthRefreshToken struct {
// ID is the internal unique identifier of the refresh token record.
ID string `json:"id"`
// Token is the SHA-256 hash or encrypted refresh token string.
Token string `json:"token"`
// ClientID is the client application holding this refresh token.
ClientID string `json:"client_id"`
// UserID is the user ID associated with the issued refresh token.
UserID string `json:"user_id"`
// SessionID is the optional session ID tied to the refresh token.
SessionID *string `json:"session_id,omitempty"`
// ReferenceID is an optional external identifier.
ReferenceID *string `json:"reference_id,omitempty"`
// FamilyID is a unique identifier linking all rotated refresh tokens in the same token family.
// If a revoked token in this family is reused, the entire family is revoked (RFC 6749 Section 10.4).
FamilyID string `json:"family_id"`
// Scopes is the list of granted scopes bound to this refresh token.
Scopes []string `json:"scopes"`
// ExpiresAt is the timestamp when the refresh token expires.
ExpiresAt time.Time `json:"expires_at"`
// CreatedAt is the timestamp when the refresh token was issued.
CreatedAt time.Time `json:"created_at"`
// RevokedAt is the timestamp when the refresh token was revoked, if applicable.
RevokedAt *time.Time `json:"revoked_at,omitempty"`
// AuthTime is the timestamp when the user originally performed authentication.
AuthTime *time.Time `json:"auth_time,omitempty"`
}
OAuthRefreshToken represents a persisted refresh token with rotation and family tracking.
type OpenIDConfigurationParams ¶
type OpenIDConfigurationParams struct {
plugin.ExtraContainer
}
OpenIDConfigurationParams defines input parameters for OpenID Provider metadata.
type OpenIDConfigurationResult ¶
type OpenIDConfigurationResult struct {
Issuer string `json:"issuer"`
AuthorizationEndpoint string `json:"authorization_endpoint"`
TokenEndpoint string `json:"token_endpoint"`
UserinfoEndpoint string `json:"userinfo_endpoint"`
IntrospectionEndpoint string `json:"introspection_endpoint"`
RevocationEndpoint string `json:"revocation_endpoint"`
EndSessionEndpoint string `json:"end_session_endpoint,omitempty"`
RegistrationEndpoint string `json:"registration_endpoint,omitempty"`
JwksURI string `json:"jwks_uri,omitempty"`
ResponseTypesSupported []string `json:"response_types_supported"`
SubjectTypesSupported []string `json:"subject_types_supported"`
IDTokenSigningAlgValuesSupported []string `json:"id_token_signing_alg_values_supported"`
ScopesSupported []string `json:"scopes_supported"`
TokenEndpointAuthMethodsSupported []string `json:"token_endpoint_auth_methods_supported"`
ClaimsSupported []string `json:"claims_supported"`
CodeChallengeMethodsSupported []string `json:"code_challenge_methods_supported"`
GrantTypesSupported []string `json:"grant_types_supported"`
}
OpenIDConfigurationResult represents discovery metadata (OpenID Connect Discovery 1.0).
type Option ¶
type Option func(*Config)
Option configures the OAuth 2.1 Provider plugin.
func WithAccessTokenType ¶
func WithAccessTokenType(t AccessTokenType) Option
WithAccessTokenType sets the Access Token format ("jwt" or "opaque").
func WithCustomAccessTokenClaims ¶
func WithCustomAccessTokenClaims(fn CustomClaimsFunc) Option
WithCustomAccessTokenClaims sets a custom claims injector for JWT Access Tokens.
func WithCustomIDTokenClaims ¶
func WithCustomIDTokenClaims(fn CustomClaimsFunc) Option
WithCustomIDTokenClaims sets a custom claims injector for OIDC ID Tokens.
func WithCustomUserInfoClaims ¶
func WithCustomUserInfoClaims(fn CustomClaimsFunc) Option
WithCustomUserInfoClaims sets a custom claims injector for the UserInfo endpoint.
func WithDynamicClientRegistration ¶
WithDynamicClientRegistration configures RFC 7591 Dynamic Client Registration.
func WithGrantTypes ¶
WithGrantTypes overrides the list of enabled grant types.
func WithIssuer ¶
WithIssuer configures the authorization server issuer URL.
func WithJWTSigner ¶
WithJWTSigner configures a custom JWT signer (such as an adapter for plugins/jwt or RSA/ECDSA signer).
func WithPairwiseSecret ¶
WithPairwiseSecret sets the secret key for deriving pairwise pseudonymous subject identifiers.
func WithScopes ¶
WithScopes overrides the list of supported OAuth/OIDC scopes.
func WithStoreModes ¶
WithStoreModes configures the storage strategy for secrets and tokens.
func WithTokenExpirations ¶
WithTokenExpirations configures expiration lifetimes for all token types.
type Plugin ¶
type Plugin struct {
// contains filtered or unexported fields
}
Plugin implements plugin.Plugin for the OAuth 2.1 & OpenID Connect Provider.
func New ¶
func New(repo Repository, opts ...Option) *Plugin
New creates a new OAuth 2.1 Provider plugin with the given repository and options.
func (*Plugin) Authorize ¶
func (p *Plugin) Authorize(ctx context.Context, params AuthorizeParams) (*AuthorizeResult, error)
Authorize handles the authorization step of the OAuth 2.1 Authorization Code Flow.
func (*Plugin) Consent ¶
func (p *Plugin) Consent(ctx context.Context, params ConsentParams) (*ConsentResult, error)
Consent processes the end-user's decision to grant or deny requested scopes.
func (*Plugin) ContinueAuthorize ¶
func (p *Plugin) ContinueAuthorize(ctx context.Context, params ContinueAuthorizeParams) (*AuthorizeResult, error)
ContinueAuthorize resumes the authorization code issuance after a user authenticates or consents.
func (*Plugin) DeleteClient ¶
func (p *Plugin) DeleteClient(ctx context.Context, params DeleteClientParams) (*DeleteClientResult, error)
DeleteClient removes an OAuth client record from storage.
func (*Plugin) EndSession ¶
func (p *Plugin) EndSession(ctx context.Context, params EndSessionParams) (*EndSessionResult, error)
EndSession implements OpenID Connect RP-Initiated Logout 1.0.
func (*Plugin) GetClient ¶
func (p *Plugin) GetClient(ctx context.Context, params GetClientParams) (*GetClientResult, error)
GetClient retrieves an OAuth client by its ClientID.
func (*Plugin) GetOAuthAuthorizationServerMetadata ¶
func (p *Plugin) GetOAuthAuthorizationServerMetadata(ctx context.Context, params OAuthMetadataParams) (*OAuthMetadataResult, error)
GetOAuthAuthorizationServerMetadata returns OAuth 2.0 Authorization Server Metadata per RFC 8414.
func (*Plugin) GetOpenIDConfiguration ¶
func (p *Plugin) GetOpenIDConfiguration(ctx context.Context, params OpenIDConfigurationParams) (*OpenIDConfigurationResult, error)
GetOpenIDConfiguration returns the OpenID Connect Discovery 1.0 metadata document.
func (*Plugin) Introspect ¶
func (p *Plugin) Introspect(ctx context.Context, params IntrospectParams) (*IntrospectResult, error)
Introspect inspects an active access token or refresh token according to RFC 7662.
func (*Plugin) ListConsents ¶
func (p *Plugin) ListConsents(ctx context.Context, params ListConsentsParams) (*ListConsentsResult, error)
ListConsents retrieves all active consents granted by a specific user.
func (*Plugin) RegisterClient ¶
func (p *Plugin) RegisterClient(ctx context.Context, params RegisterClientParams) (*RegisterClientResult, error)
RegisterClient performs RFC 7591 Dynamic Client Registration or programmatic client creation.
func (*Plugin) Repository ¶
func (p *Plugin) Repository() Repository
Repository returns the underlying storage repository.
func (*Plugin) RequireScope ¶ added in v0.20.0
RequireScope returns a net/http middleware handler verifying valid OAuth2 Access Token and required scopes.
func (*Plugin) Revoke ¶
func (p *Plugin) Revoke(ctx context.Context, params RevokeParams) (*RevokeResult, error)
Revoke revokes an access token or refresh token according to RFC 7009.
func (*Plugin) RevokeConsent ¶
func (p *Plugin) RevokeConsent(ctx context.Context, params RevokeConsentParams) (*RevokeConsentResult, error)
RevokeConsent revokes all scopes previously granted by a user to a specific OAuth client.
func (*Plugin) RotateClientSecret ¶
func (p *Plugin) RotateClientSecret(ctx context.Context, params RotateClientSecretParams) (*RotateClientSecretResult, error)
RotateClientSecret generates and replaces the client secret for a confidential OAuth client.
func (*Plugin) Token ¶
func (p *Plugin) Token(ctx context.Context, params TokenParams) (*TokenResult, error)
Token handles token exchanges across all supported OAuth 2.1 grant types: "authorization_code", "refresh_token", and "client_credentials".
func (*Plugin) UpdateClient ¶
func (p *Plugin) UpdateClient(ctx context.Context, params UpdateClientParams) (*UpdateClientResult, error)
UpdateClient updates mutable properties of an existing OAuth client.
func (*Plugin) UserInfo ¶
func (p *Plugin) UserInfo(ctx context.Context, params UserInfoParams) (*UserInfoResult, error)
UserInfo resolves the claims of the authenticated user for the given access token (OIDC Core 1.0).
type RegisterClientParams ¶
type RegisterClientParams struct {
ClientName string `json:"client_name"`
ClientURI string `json:"client_uri,omitempty"`
LogoURI string `json:"logo_uri,omitempty"`
Contacts []string `json:"contacts,omitempty"`
TOSURI string `json:"tos_uri,omitempty"`
PolicyURI string `json:"policy_uri,omitempty"`
SoftwareID string `json:"software_id,omitempty"`
SoftwareVersion string `json:"software_version,omitempty"`
RedirectURIs []string `json:"redirect_uris"`
PostLogoutRedirectURIs []string `json:"post_logout_redirect_uris,omitempty"`
TokenEndpointAuthMethod TokenEndpointAuthMethod `json:"token_endpoint_auth_method,omitempty"`
GrantTypes []GrantType `json:"grant_types,omitempty"`
ResponseTypes []ResponseType `json:"response_types,omitempty"`
Scope string `json:"scope,omitempty"`
Public bool `json:"public,omitempty"`
SubjectType SubjectType `json:"subject_type,omitempty"`
SkipConsent bool `json:"skip_consent,omitempty"`
EnableEndSession bool `json:"enable_end_session,omitempty"`
UserID *string `json:"user_id,omitempty"`
Metadata map[string]any `json:"metadata,omitempty"`
plugin.ExtraContainer
}
RegisterClientParams defines input parameters for Dynamic Client Registration (RFC 7591).
type RegisterClientResult ¶
type RegisterClientResult struct {
Client *OAuthClient `json:"client"`
ClientID string `json:"client_id"`
ClientSecret string `json:"client_secret,omitempty"`
}
RegisterClientResult contains the registered client entity and generated secrets.
type Repository ¶
type Repository interface {
// FindClientByClientID retrieves an OAuth client by its public ClientID string.
//
// Function:
// Called during authorize, token exchange, client auth, and introspection endpoints.
//
// Storage:
// Both (Cache-Aside Strategy) - Cached by client_id in Redis/memory.
//
// Arguments:
// - ctx: Request cancellation context.
// - clientID: Public client_id string.
//
// Returns:
// - *OAuthClient: Matching client entity if found.
// - error: ErrClientNotFound if missing, or database error.
//
// Example SQL:
// SELECT id, client_id, client_secret, name, redirect_uris, grant_types, created_at, updated_at FROM oauth_clients WHERE client_id = $1 LIMIT 1;
//
// Example Cache (Redis):
// val, err := rdb.Get(ctx, "oauth:client:" + clientID).Bytes()
FindClientByClientID(ctx context.Context, clientID string) (*OAuthClient, error)
// FindClientByID retrieves an OAuth client by its primary database record ID.
//
// Function:
// Used in administrative client management panels.
//
// Storage:
// Database (GORM / SQL) - Client primary key lookup.
//
// Arguments:
// - ctx: Request cancellation context.
// - id: Primary key record ID.
//
// Returns:
// - *OAuthClient: Matching client entity.
// - error: ErrClientNotFound if missing.
//
// Example SQL:
// SELECT id, client_id, client_secret, name, redirect_uris, grant_types, created_at, updated_at FROM oauth_clients WHERE id = $1 LIMIT 1;
FindClientByID(ctx context.Context, id string) (*OAuthClient, error)
// ListClientsByUserID retrieves all OAuth clients owned/registered by a specific user.
//
// Function:
// Used in user settings UI to display user-created OAuth applications.
//
// Storage:
// Database (GORM / SQL) - Relational list query.
//
// Arguments:
// - ctx: Request cancellation context.
// - userID: Target user ID.
//
// Returns:
// - []*OAuthClient: Slice of client entities.
// - error: Nil on success.
//
// Example SQL:
// SELECT id, client_id, client_secret, name, redirect_uris, grant_types, created_at, updated_at FROM oauth_clients WHERE user_id = $1;
ListClientsByUserID(ctx context.Context, userID string) ([]*OAuthClient, error)
// CreateClient persists a newly registered OAuth client.
//
// Function:
// Called during dynamic client registration or administrative application onboarding.
//
// Storage:
// Database (GORM / SQL) - Relational insert.
//
// Arguments:
// - ctx: Request cancellation context.
// - client: OAuthClient entity to persist.
//
// Returns:
// - error: Nil on success, or database error.
//
// Example SQL:
// INSERT INTO oauth_clients (id, client_id, client_secret, name, redirect_uris, grant_types, created_at, updated_at)
// VALUES ($1, $2, $3, $4, $5, $6, $7, $8);
CreateClient(ctx context.Context, client *OAuthClient) error
// UpdateClient updates mutable fields of an existing OAuth client.
//
// Function:
// Called when updating client settings, redirect URIs, or secret keys.
//
// Storage:
// Database (GORM / SQL) - Relational update.
//
// Arguments:
// - ctx: Request cancellation context.
// - client: Modified OAuthClient entity.
//
// Returns:
// - error: Nil on success.
//
// Example SQL:
// UPDATE oauth_clients SET name = $1, redirect_uris = $2, grant_types = $3, updated_at = $4 WHERE client_id = $5;
UpdateClient(ctx context.Context, client *OAuthClient) error
// DeleteClient removes an OAuth client record from storage by its client_id.
//
// Function:
// Called when unregistering an OAuth application.
//
// Storage:
// Database (GORM / SQL) - Record deletion.
//
// Arguments:
// - ctx: Request cancellation context.
// - clientID: Public client ID string.
//
// Returns:
// - error: Nil on success.
//
// Example SQL:
// DELETE FROM oauth_clients WHERE client_id = $1;
DeleteClient(ctx context.Context, clientID string) error
// CreateAuthorizationCode persists a single-use authorization code record.
//
// Function:
// Called at the completion of the interactive authorization code flow.
//
// Storage:
// Cache (Redis / In-Memory TTL) - Short-lived authorization code state.
//
// Arguments:
// - ctx: Request cancellation context.
// - code: OAuthAuthorizationCode entity containing code secret, PKCE challenge, and scopes.
//
// Returns:
// - error: Nil on success.
//
// Example SQL:
// INSERT INTO oauth_codes (id, code, client_id, user_id, redirect_uri, scope, code_challenge, code_challenge_method, expires_at, created_at)
// VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10);
//
// Example Cache (Redis):
// err := rdb.Set(ctx, "oauth:code:" + code.Code, bytes, ttl).Err()
CreateAuthorizationCode(ctx context.Context, code *OAuthAuthorizationCode) error
// ConsumeAuthorizationCode atomically finds and removes (or marks consumed) an authorization code in a single step.
// This atomic operation guarantees anti-replay protection and race condition prevention.
//
// Function:
// Called during authorization_code token exchange.
//
// Storage:
// Cache (Redis GETDEL / Memory) - Atomic read-and-delete single-use code consumption.
//
// Arguments:
// - ctx: Request cancellation context.
// - code: Raw code secret string.
//
// Returns:
// - *OAuthAuthorizationCode: Consumed authorization code record.
// - error: ErrInvalidAuthorizationCode if missing or expired.
//
// Example SQL:
// DELETE FROM oauth_codes WHERE code = $1 AND expires_at > $2 RETURNING id, code, client_id, user_id, redirect_uri, scope, code_challenge, code_challenge_method, expires_at, created_at;
//
// Example Cache (Redis):
// val, err := rdb.GetDel(ctx, "oauth:code:" + code).Bytes()
ConsumeAuthorizationCode(ctx context.Context, code string) (*OAuthAuthorizationCode, error)
// CreateAccessToken persists an issued access token.
//
// Function:
// Called during token generation in token endpoints.
//
// Storage:
// Database (GORM / SQL) - Token persistence.
//
// Arguments:
// - ctx: Request cancellation context.
// - token: OAuthAccessToken entity containing hashed token, client ID, user ID, scopes, and expiry.
//
// Returns:
// - error: Nil on success.
//
// Example SQL:
// INSERT INTO oauth_access_tokens (id, token_hash, client_id, user_id, scope, expires_at, created_at)
// VALUES ($1, $2, $3, $4, $5, $6, $7);
CreateAccessToken(ctx context.Context, token *OAuthAccessToken) error
// FindAccessToken retrieves an access token record by its token hash.
//
// Function:
// Called during RFC 7662 Introspection or API bearer authorization validation.
//
// Storage:
// Both (Cache-Aside Strategy) - Cached in Redis (`oauth:token:<tokenHash>`) for fast token validation.
//
// Arguments:
// - ctx: Request cancellation context.
// - tokenHash: SHA-256 hash of the bearer token string.
//
// Returns:
// - *OAuthAccessToken: Matching token record if found.
// - error: ErrInvalidAccessToken if missing or expired.
//
// Example SQL:
// SELECT id, token_hash, client_id, user_id, scope, expires_at, created_at FROM oauth_access_tokens WHERE token_hash = $1 LIMIT 1;
//
// Example Cache (Redis):
// val, err := rdb.Get(ctx, "oauth:token:" + tokenHash).Bytes()
FindAccessToken(ctx context.Context, tokenHash string) (*OAuthAccessToken, error)
// DeleteAccessToken removes an access token from storage upon revocation or expiration.
//
// Function:
// Called during RFC 7009 token revocation.
//
// Storage:
// Database (GORM / SQL) - Token revocation deletion.
//
// Arguments:
// - ctx: Request cancellation context.
// - tokenHash: Token hash.
//
// Returns:
// - error: Nil on success.
//
// Example SQL:
// DELETE FROM oauth_access_tokens WHERE token_hash = $1;
DeleteAccessToken(ctx context.Context, tokenHash string) error
// CreateRefreshToken persists an issued refresh token with its family ID.
//
// Function:
// Called during token issuance for offline_access grants.
//
// Storage:
// Database (GORM / SQL) - Refresh token record insertion.
//
// Arguments:
// - ctx: Request cancellation context.
// - token: OAuthRefreshToken entity containing token hash, family ID, and revocation state.
//
// Returns:
// - error: Nil on success.
//
// Example SQL:
// INSERT INTO oauth_refresh_tokens (id, token_hash, family_id, client_id, user_id, scope, revoked, expires_at, created_at)
// VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9);
CreateRefreshToken(ctx context.Context, token *OAuthRefreshToken) error
// FindRefreshToken retrieves a refresh token record by its token hash.
//
// Function:
// Called during refresh_token grant type token renewal.
//
// Storage:
// Database (GORM / SQL) - Refresh token query.
//
// Arguments:
// - ctx: Request cancellation context.
// - tokenHash: SHA-256 hash of the refresh token.
//
// Returns:
// - *OAuthRefreshToken: Refresh token entity if valid.
// - error: ErrInvalidRefreshToken if missing or expired, ErrRefreshTokenRevoked if revoked.
//
// Example SQL:
// SELECT id, token_hash, family_id, client_id, user_id, scope, revoked, expires_at, created_at FROM oauth_refresh_tokens WHERE token_hash = $1 LIMIT 1;
FindRefreshToken(ctx context.Context, tokenHash string) (*OAuthRefreshToken, error)
// DeleteRefreshToken removes a single refresh token from storage.
//
// Function:
// Called when consuming a refresh token during rotation.
//
// Storage:
// Database (GORM / SQL) - Single refresh token deletion.
//
// Arguments:
// - ctx: Request cancellation context.
// - tokenHash: Token hash.
//
// Returns:
// - error: Nil on success.
//
// Example SQL:
// DELETE FROM oauth_refresh_tokens WHERE token_hash = $1;
DeleteRefreshToken(ctx context.Context, tokenHash string) error
// RevokeRefreshTokenFamily invalidates all refresh tokens and associated access tokens in a token family.
//
// Function:
// Called when refresh token reuse is detected (detecting token theft attack).
//
// Storage:
// Database (GORM / SQL) - Token family revocation update.
//
// Arguments:
// - ctx: Request cancellation context.
// - familyID: Token family identifier string.
//
// Returns:
// - error: Nil on success.
//
// Example SQL:
// UPDATE oauth_refresh_tokens SET revoked = true WHERE family_id = $1;
RevokeRefreshTokenFamily(ctx context.Context, familyID string) error
// FindConsent retrieves user consent granted to a client application.
//
// Function:
// Used during authorize request to check if user has previously approved scopes.
//
// Storage:
// Database (GORM / SQL) - Consent record query.
//
// Arguments:
// - ctx: Request cancellation context.
// - clientID: Target client ID.
// - userID: Target user ID.
//
// Returns:
// - *OAuthConsent: Matching consent entity if found.
// - error: ErrConsentRequired if not consented.
//
// Example SQL:
// SELECT id, client_id, user_id, scopes, created_at, updated_at FROM oauth_consents WHERE client_id = $1 AND user_id = $2 LIMIT 1;
FindConsent(ctx context.Context, clientID, userID string) (*OAuthConsent, error)
// ListConsentsByUserID retrieves all active consents granted by a specific user.
//
// Function:
// Used in user security settings panel to show connected applications.
//
// Storage:
// Database (GORM / SQL) - User consents list query.
//
// Arguments:
// - ctx: Request cancellation context.
// - userID: Target user ID.
//
// Returns:
// - []*OAuthConsent: Slice of consents.
// - error: Nil on success.
//
// Example SQL:
// SELECT id, client_id, user_id, scopes, created_at, updated_at FROM oauth_consents WHERE user_id = $1;
ListConsentsByUserID(ctx context.Context, userID string) ([]*OAuthConsent, error)
// CreateConsent records a newly granted user consent.
//
// Function:
// Called after user approves authorization prompt.
//
// Storage:
// Database (GORM / SQL) - Consent entity creation.
//
// Arguments:
// - ctx: Request cancellation context.
// - consent: OAuthConsent entity.
//
// Returns:
// - error: Nil on success.
//
// Example SQL:
// INSERT INTO oauth_consents (id, client_id, user_id, scopes, created_at, updated_at) VALUES ($1, $2, $3, $4, $5, $6);
CreateConsent(ctx context.Context, consent *OAuthConsent) error
// UpdateConsent updates the granted scopes of an existing consent.
//
// Function:
// Called when user grants additional scopes to an already authorized app.
//
// Storage:
// Database (GORM / SQL) - Consent scopes update.
//
// Arguments:
// - ctx: Request cancellation context.
// - consent: Modified OAuthConsent entity.
//
// Returns:
// - error: Nil on success.
//
// Example SQL:
// UPDATE oauth_consents SET scopes = $1, updated_at = $2 WHERE id = $3;
UpdateConsent(ctx context.Context, consent *OAuthConsent) error
// DeleteConsent revokes and removes a user consent record.
//
// Function:
// Called when a user disconnects an authorized application.
//
// Storage:
// Database (GORM / SQL) - Consent deletion.
//
// Arguments:
// - ctx: Request cancellation context.
// - id: Primary key record ID.
//
// Returns:
// - error: Nil on success.
//
// Example SQL:
// DELETE FROM oauth_consents WHERE id = $1;
DeleteConsent(ctx context.Context, id string) error
// FindUserByID retrieves a user domain entity by user ID.
//
// Function:
// Used during UserInfo endpoint processing or authorization prompt rendering.
//
// Storage:
// Database (GORM / SQL) - User entity lookup.
//
// Arguments:
// - ctx: Request cancellation context.
// - userID: Target user ID.
//
// Returns:
// - *entity.User: Matching user entity if found.
// - error: ErrInvalidClient/ErrUserNotFound if missing.
//
// Example SQL:
// SELECT id, email, name, email_verified, created_at, updated_at FROM users WHERE id = $1 LIMIT 1;
FindUserByID(ctx context.Context, userID string) (*entity.User, error)
// FindSessionByID retrieves an active session domain entity by session ID.
//
// Function:
// Used during authorize prompt check or RP-Initiated Logout.
//
// Storage:
// Both (Cache-Aside Strategy) - Session retrieval by ID.
//
// Arguments:
// - ctx: Request cancellation context.
// - sessionID: Session identifier.
//
// Returns:
// - *entity.Session: Active session entity if found.
// - error: ErrLoginRequired if missing or expired.
//
// Example SQL:
// SELECT id, user_id, token, expires_at, created_at, updated_at FROM sessions WHERE id = $1 LIMIT 1;
//
// Example Cache (Redis):
// val, err := rdb.Get(ctx, "session:" + sessionID).Bytes()
FindSessionByID(ctx context.Context, sessionID string) (*entity.Session, error)
// DeleteSessionByID deletes a session upon RP-Initiated Logout.
//
// Function:
// Called during OpenID Connect end-session logout endpoint.
//
// Storage:
// Database (GORM / SQL) - Session deletion.
//
// Arguments:
// - ctx: Request cancellation context.
// - sessionID: Session identifier.
//
// Returns:
// - error: Nil on success.
//
// Example SQL:
// DELETE FROM sessions WHERE id = $1;
DeleteSessionByID(ctx context.Context, sessionID string) error
}
Repository defines the storage contract required by the OAuth 2.1 Provider plugin. Implement this interface on your custom database adapter (e.g. PostgreSQL, MySQL, SQLite, MongoDB, GORM).
Implementation Example (GORM / database/sql): ¶
type GormOAuth2Repository struct {
db *gorm.DB
}
func (r *GormOAuth2Repository) FindClientByClientID(ctx context.Context, clientID string) (*oauth2.OAuthClient, error) {
var c oauth2.OAuthClient
if err := r.db.WithContext(ctx).Where("client_id = ?", clientID).First(&c).Error; err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, oauth2.ErrClientNotFound
}
return nil, err
}
return &c, nil
}
Storage and Caching Recommendation (Token Introspection & Authorization Code Cache): ¶
Access Tokens and Authorization Codes can be cached in Redis to achieve high-throughput introspection:
Authorization Codes (`ConsumeAuthorizationCode`): Store ephemeral codes in Redis (`oauth:code:<code>`) with short TTL. Use `GETDEL` for single-use consumption.
Access Token Introspection (`FindAccessToken`): Cache active token hashes in Redis (`oauth:token:<hash>`) with TTL equal to token remaining lifetime.
Recommended Caching Decorator Example:
type CachedOAuth2Repository struct {
dbRepo oauth2.Repository
redis *redis.Client
}
func (r *CachedOAuth2Repository) FindAccessToken(ctx context.Context, tokenHash string) (*oauth2.OAuthAccessToken, error) {
val, err := r.redis.Get(ctx, "oauth:token:"+tokenHash).Bytes()
if err == nil {
var token oauth2.OAuthAccessToken
if json.Unmarshal(val, &token) == nil {
return &token, nil // Fast Introspection Cache Hit
}
}
token, err := r.dbRepo.FindAccessToken(ctx, tokenHash)
if err == nil {
bytes, _ := json.Marshal(token)
ttl := time.Until(token.ExpiresAt)
r.redis.Set(ctx, "oauth:token:"+tokenHash, bytes, ttl)
}
return token, err
}
type ResponseType ¶
type ResponseType string
ResponseType represents the authorization endpoint response type.
const ( // ResponseTypeCode represents the authorization code response type ("code"). ResponseTypeCode ResponseType = "code" )
type RevokeConsentParams ¶
type RevokeConsentParams struct {
ClientID string `json:"client_id"`
UserID string `json:"user_id"`
plugin.ExtraContainer
}
RevokeConsentParams defines input parameters to revoke user consent for a client.
type RevokeConsentResult ¶
type RevokeConsentResult struct {
Success bool `json:"success"`
}
RevokeConsentResult reports the outcome of revoking consent.
type RevokeParams ¶
type RevokeParams struct {
Token string `json:"token"`
TokenTypeHint string `json:"token_type_hint,omitempty"`
ClientID string `json:"client_id,omitempty"`
ClientSecret string `json:"client_secret,omitempty"`
plugin.ExtraContainer
}
RevokeParams defines input parameters for token revocation (RFC 7009).
type RevokeResult ¶
type RevokeResult struct {
Success bool `json:"success"`
}
RevokeResult reports the result of token revocation.
type RotateClientSecretParams ¶
type RotateClientSecretParams struct {
ClientID string `json:"client_id"`
plugin.ExtraContainer
}
RotateClientSecretParams defines input parameters to rotate a client secret.
type RotateClientSecretResult ¶
type RotateClientSecretResult struct {
ClientID string `json:"client_id"`
NewClientSecret string `json:"new_client_secret"`
}
RotateClientSecretResult contains the new raw client secret.
type SessionEndedEventPayload ¶
type SessionEndedEventPayload struct {
// UserID is the user ID whose session ended.
UserID string `json:"user_id"`
// ClientID is the client that initiated the logout, if known.
ClientID string `json:"client_id,omitempty"`
// PostLogoutRedirectURI is the redirect destination after logout.
PostLogoutRedirectURI string `json:"post_logout_redirect_uri,omitempty"`
// Timestamp is the moment the session ended.
Timestamp time.Time `json:"timestamp"`
}
SessionEndedEventPayload represents the payload dispatched when RP-Initiated Logout completes.
type StoreMode ¶
type StoreMode string
StoreMode defines how secrets, authorization codes, and tokens are stored in the database.
const ( // StoreModePlain stores tokens and secrets in plain text (suitable for local dev/testing). StoreModePlain StoreMode = "plain" // StoreModeHashed stores tokens and secrets hashed via SHA-256. StoreModeHashed StoreMode = "hashed" // StoreModeEncrypted stores tokens and secrets encrypted via AES-256-GCM. StoreModeEncrypted StoreMode = "encrypted" )
type SubjectType ¶
type SubjectType string
SubjectType defines how the subject identifier (sub claim) is generated in OpenID Connect.
const ( // SubjectTypePublic issues the exact same sub identifier across all clients. SubjectTypePublic SubjectType = "public" // SubjectTypePairwise issues client-specific pseudonymous sub identifiers. SubjectTypePairwise SubjectType = "pairwise" )
type TokenEndpointAuthMethod ¶
type TokenEndpointAuthMethod string
TokenEndpointAuthMethod specifies client authentication methods at the token endpoint.
const ( // AuthMethodClientSecretBasic authenticates via HTTP Basic Authorization header. AuthMethodClientSecretBasic TokenEndpointAuthMethod = "client_secret_basic" // AuthMethodClientSecretPost authenticates via POST body parameters (client_id & client_secret). AuthMethodClientSecretPost TokenEndpointAuthMethod = "client_secret_post" // AuthMethodNone indicates no client authentication (public clients with PKCE). AuthMethodNone TokenEndpointAuthMethod = "none" )
type TokenIssuedEventPayload ¶
type TokenIssuedEventPayload struct {
// ClientID is the client receiving tokens.
ClientID string `json:"client_id"`
// UserID is the user ID if issued in user context (nil for M2M client credentials).
UserID *string `json:"user_id,omitempty"`
// GrantType is the grant type used for issuance.
GrantType GrantType `json:"grant_type"`
// Scopes is the list of scopes granted to the tokens.
Scopes []string `json:"scopes"`
// AccessToken is the raw access token string.
AccessToken string `json:"access_token"`
// RefreshToken is the raw refresh token string, if issued.
RefreshToken *string `json:"refresh_token,omitempty"`
// IDToken is the raw ID token string, if issued.
IDToken *string `json:"id_token,omitempty"`
// Timestamp is the moment the tokens were issued.
Timestamp time.Time `json:"timestamp"`
}
TokenIssuedEventPayload represents the payload dispatched when tokens are minted.
type TokenParams ¶
type TokenParams struct {
GrantType string `json:"grant_type"`
Code string `json:"code,omitempty"`
CodeVerifier string `json:"code_verifier,omitempty"`
RedirectURI string `json:"redirect_uri,omitempty"`
ClientID string `json:"client_id,omitempty"`
ClientSecret string `json:"client_secret,omitempty"`
RefreshToken string `json:"refresh_token,omitempty"`
Scope string `json:"scope,omitempty"`
Resource string `json:"resource,omitempty"`
plugin.ExtraContainer
}
TokenParams defines input parameters for the token endpoint exchange.
type TokenRefreshedEventPayload ¶
type TokenRefreshedEventPayload struct {
// ClientID is the client refreshing tokens.
ClientID string `json:"client_id"`
// UserID is the user ID associated with the tokens.
UserID string `json:"user_id"`
// FamilyID is the token family identifier.
FamilyID string `json:"family_id"`
// NewAccessToken is the newly issued access token.
NewAccessToken string `json:"new_access_token"`
// NewRefreshToken is the newly rotated refresh token.
NewRefreshToken string `json:"new_refresh_token"`
// Timestamp is the moment the refresh occurred.
Timestamp time.Time `json:"timestamp"`
}
TokenRefreshedEventPayload represents the payload dispatched upon token refresh rotation.
type TokenResult ¶
type TokenResult struct {
AccessToken string `json:"access_token"`
TokenType string `json:"token_type"`
ExpiresIn int64 `json:"expires_in"`
RefreshToken string `json:"refresh_token,omitempty"`
IDToken string `json:"id_token,omitempty"`
Scope string `json:"scope,omitempty"`
}
TokenResult represents the response issued by the token endpoint.
type TokenRevokedEventPayload ¶
type TokenRevokedEventPayload struct {
// TokenHash is the SHA-256 hash of the revoked token.
TokenHash string `json:"token_hash"`
// TokenType is the hinted type ("access_token" or "refresh_token").
TokenType string `json:"token_type"`
// ClientID is the client ID associated with the token, if known.
ClientID string `json:"client_id,omitempty"`
// Timestamp is the moment revocation occurred.
Timestamp time.Time `json:"timestamp"`
}
TokenRevokedEventPayload represents the payload dispatched when a token is revoked.
type UpdateClientParams ¶
type UpdateClientParams struct {
ClientID string `json:"client_id"`
ClientName *string `json:"client_name,omitempty"`
ClientURI *string `json:"client_uri,omitempty"`
LogoURI *string `json:"logo_uri,omitempty"`
Contacts []string `json:"contacts,omitempty"`
RedirectURIs []string `json:"redirect_uris,omitempty"`
PostLogoutRedirectURIs []string `json:"post_logout_redirect_uris,omitempty"`
GrantTypes []GrantType `json:"grant_types,omitempty"`
Scopes []string `json:"scopes,omitempty"`
SkipConsent *bool `json:"skip_consent,omitempty"`
EnableEndSession *bool `json:"enable_end_session,omitempty"`
Disabled *bool `json:"disabled,omitempty"`
Metadata map[string]any `json:"metadata,omitempty"`
plugin.ExtraContainer
}
UpdateClientParams defines input parameters to update an OAuth client.
type UpdateClientResult ¶
type UpdateClientResult struct {
Client *OAuthClient `json:"client"`
}
UpdateClientResult contains the updated client entity.
type UserInfoParams ¶
type UserInfoParams struct {
AccessToken string `json:"access_token"`
plugin.ExtraContainer
}
UserInfoParams defines input parameters for the OIDC UserInfo endpoint.
type UserInfoResult ¶
type UserInfoResult struct {
Sub string `json:"sub"`
Name string `json:"name,omitempty"`
Email string `json:"email,omitempty"`
EmailVerified *bool `json:"email_verified,omitempty"`
PhoneNumber string `json:"phone_number,omitempty"`
PhoneNumberVerified *bool `json:"phone_number_verified,omitempty"`
Picture string `json:"picture,omitempty"`
Claims map[string]any `json:"claims,omitempty"`
}
UserInfoResult represents claims returned by the OIDC UserInfo endpoint.