Documentation
¶
Overview ¶
Package oauth implements OAuth 2.0 client authentication and social account linking for Google, GitHub, and custom providers with PKCE support.
Index ¶
- Constants
- Variables
- func ComputeS256Challenge(verifier string) string
- func RegisterSchema(s *schema.Schema) error
- func VerifyPKCE(verifier, challenge, method string) bool
- type AccountLinkedPayload
- type AccountUnlinkedPayload
- type Action
- type AuthResult
- type AuthenticatedPayload
- type BeginAuthInput
- type BeginAuthResult
- type BeginLinkInput
- type CompleteAuthInput
- type CompleteLinkInput
- type Config
- type FailedPayload
- type Hooks
- func (h *Hooks) AfterOAuthSignIn(fn func(ctx context.Context, res *AuthResult) error)
- func (h *Hooks) AfterProfileFetched(fn func(ctx context.Context, profile *provider.ProviderProfile) error)
- func (h *Hooks) BeforeAccountLink(...)
- func (h *Hooks) BeforeOAuthRedirect(fn func(ctx context.Context, in *BeginAuthInput) error)
- func (h *Hooks) BeforeTokenExchange(fn func(ctx context.Context, providerName string, code string) error)
- type LinkResult
- type LinkingPolicy
- type Module
- type OAuth
- type Option
- func WithAllowOrphanUser(allow bool) Option
- func WithAllowSignUp(allow bool) Option
- func WithDefaultPKCE(usePKCE bool) Option
- func WithHooks(h *Hooks) Option
- func WithLinkingPolicy(policy LinkingPolicy) Option
- func WithProvider(p provider.Provider) Option
- func WithProviders(providers ...provider.Provider) Option
- func WithStateTTL(d time.Duration) Option
- type PKCEPair
- type StateCreatedPayload
- type StateSession
- type UserCreatedPayload
Constants ¶
const ( // EventOAuthStateCreated is emitted when a new OAuth state session is initiated. EventOAuthStateCreated auth.EventName = "oauth.state_created" // EventOAuthAuthenticated is emitted when a user successfully authenticates via OAuth. EventOAuthAuthenticated auth.EventName = "oauth.authenticated" // EventOAuthUserCreated is emitted when a new Core User is registered during OAuth flow. EventOAuthUserCreated auth.EventName = "oauth.user_created" // EventOAuthAccountLinked is emitted when a provider account is linked to a Core User. EventOAuthAccountLinked auth.EventName = "oauth.account_linked" // EventOAuthAccountUnlinked is emitted when a provider account link is removed. EventOAuthAccountUnlinked auth.EventName = "oauth.account_unlinked" // EventOAuthFailed is emitted when an OAuth authentication flow fails. EventOAuthFailed auth.EventName = "oauth.failed" )
OAuth event names published through the core Event dispatcher.
const ( // PKCEMethodS256 is the standard SHA-256 PKCE code challenge method. PKCEMethodS256 = "S256" // PKCEMethodPlain is the plain text PKCE method (RFC 7636 allows it, but S256 is strictly preferred). PKCEMethodPlain = "plain" // DefaultVerifierByteLength generates 32 bytes of entropy, producing 43 base64url characters. DefaultVerifierByteLength = 32 )
const ( // DefaultStateTTL is the default validity duration for an in-flight OAuth state session (10 minutes). DefaultStateTTL = 10 * time.Minute )
const (
ModelOAuthStates = "oauth_states"
)
Variables ¶
var ( // ErrProviderNotFound is returned when attempting to use a provider that was not registered. ErrProviderNotFound = errors.New("oauth: provider not found") // ErrProviderAlreadyExists is returned when registering a provider with a duplicate name. ErrProviderAlreadyExists = errors.New("oauth: provider already registered") // ErrInvalidState is returned when an OAuth state string is malformed or invalid. ErrInvalidState = errors.New("oauth: invalid state") // ErrStateNotFound is returned when the state session does not exist in store. ErrStateNotFound = errors.New("oauth: state session not found") // ErrStateExpired is returned when the state session has expired. ErrStateExpired = errors.New("oauth: state session expired") // ErrStateAlreadyConsumed is returned when a state session was already used (anti-replay). ErrStateAlreadyConsumed = errors.New("oauth: state session already consumed") // ErrInvalidRedirectURI is returned when the supplied redirect URI is not in the provider's allowed list or mismatches the initiated flow. ErrInvalidRedirectURI = errors.New("oauth: invalid redirect uri") // ErrPKCEMismatch is returned when PKCE verification fails. ErrPKCEMismatch = errors.New("oauth: pkce verification failed") // ErrTokenExchangeFailed is returned when exchanging the authorization code with the provider fails. ErrTokenExchangeFailed = errors.New("oauth: token exchange failed") // ErrProfileFetchFailed is returned when fetching the user profile from the provider fails. ErrProfileFetchFailed = errors.New("oauth: profile fetch failed") // ErrInvalidProfile is returned when the provider profile lacks essential identity claims (e.g. subject / ID). ErrInvalidProfile = errors.New("oauth: invalid provider profile") // ErrAccountConflict is returned when an existing user with the same email exists but account linking is disabled. ErrAccountConflict = errors.New("oauth: account with this email already exists") // ErrAccountLinkingRequiresConsent is returned when an OAuth login matches an existing user's email, // but automatic linking is prohibited without explicit authentication and linking consent. // This prevents unsafe automatic account linking attacks. ErrAccountLinkingRequiresConsent = errors.New("oauth: existing user found; explicit account linking required") // ErrUnverifiedEmailLinkingProhibited is returned when automatic account linking is requested // for an email that is not verified either by the provider or within core. ErrUnverifiedEmailLinkingProhibited = errors.New("oauth: cannot link account with unverified email") // ErrAccountAlreadyLinked is returned when the provider account is already linked to another user. ErrAccountAlreadyLinked = errors.New("oauth: provider account is already linked to a user") // ErrCannotUnlinkSoleAuthMethod is returned when unlinking an OAuth provider would leave the user without any credentials or accounts. ErrCannotUnlinkSoleAuthMethod = errors.New("oauth: cannot unlink sole authentication method") // ErrSignUpDisabled is returned when a new user attempts to sign up via OAuth but automatic sign up is disabled. ErrSignUpDisabled = errors.New("oauth: sign up is disabled for new users") // ErrInvalidAction is returned when a state session action does not match the attempted completion flow. ErrInvalidAction = errors.New("oauth: state action mismatch") // ErrInvalidInput is returned when required parameters are missing or invalid. ErrInvalidInput = errors.New("oauth: invalid input") // ErrAccountNotFound is returned when an account lookup yields no record. ErrAccountNotFound = errors.New("oauth: account not found") )
Functions ¶
func ComputeS256Challenge ¶
ComputeS256Challenge calculates the BASE64URL-ENCODED SHA-256 challenge from a code verifier.
func RegisterSchema ¶
RegisterSchema registers the OAuth transient state session model.
func VerifyPKCE ¶
VerifyPKCE validates that a code verifier matches the code challenge using the specified method.
Types ¶
type AccountLinkedPayload ¶
type AccountLinkedPayload struct {
UserID string `json:"user_id"`
AccountID string `json:"account_id"`
Provider string `json:"provider"`
ProviderID string `json:"provider_id"`
}
AccountLinkedPayload contains details for account link events.
type AccountUnlinkedPayload ¶
type AccountUnlinkedPayload struct {
UserID string `json:"user_id"`
AccountID string `json:"account_id"`
Provider string `json:"provider"`
}
AccountUnlinkedPayload contains details for account unlink events.
type AuthResult ¶
type AuthResult struct {
// User is the resolved or newly created Core User.
User *user.User
// Account is the Core Account linking the User to this OAuth provider.
Account *account.Account
// Session is the newly issued Core Session.
Session *session.Session
// Token is the plaintext session token returned strictly once at session creation.
Token string
// IsNewUser indicates whether this authentication caused a new user to be registered.
IsNewUser bool
// TokenResponse holds the tokens returned by the OAuth provider.
TokenResponse *provider.TokenResponse
// Profile holds the normalized profile attributes fetched from the provider.
Profile *provider.ProviderProfile
}
AuthResult represents the outcome of a successful OAuth authentication flow.
type AuthenticatedPayload ¶
type AuthenticatedPayload struct {
UserID string `json:"user_id"`
AccountID string `json:"account_id"`
Provider string `json:"provider"`
ProviderID string `json:"provider_id"`
IsNewUser bool `json:"is_new_user"`
}
AuthenticatedPayload contains details for successful authentication.
type BeginAuthInput ¶
type BeginAuthInput struct {
// Provider is the identifier of the registered OAuth provider (e.g. "google").
Provider string
// RedirectURI is the target callback URI to which the provider should redirect.
RedirectURI string
// Scopes specifies scopes for this request, overriding provider defaults if provided.
Scopes []string
// Prompt controls the IdP prompt behavior (e.g. "consent", "select_account").
Prompt string
// AccessType controls whether offline access / refresh tokens are requested ("offline").
AccessType string
// Metadata stores custom client state associated with this in-flight flow.
Metadata map[string]string
// UsePKCE overrides the default PKCE setting for this request (nil uses plugin default, which is true).
UsePKCE *bool
}
BeginAuthInput contains parameters for initiating an OAuth authorization code flow.
type BeginAuthResult ¶
type BeginAuthResult struct {
// AuthURL is the complete provider URL the client browser should navigate to.
AuthURL string
// State is the unique, cryptographically random state identifier.
State string
// CodeVerifier is the generated PKCE verifier (stored securely in state session).
CodeVerifier string
// ExpiresAt specifies when the state session expires.
ExpiresAt time.Time
}
BeginAuthResult contains the computed authorization URL and state session metadata.
type BeginLinkInput ¶
type BeginLinkInput struct {
// UserID is the ID of the currently authenticated Core user who is linking an account.
UserID string
// Provider is the identifier of the registered OAuth provider.
Provider string
// RedirectURI is the callback URI.
RedirectURI string
// Scopes specifies requested scopes.
Scopes []string
// Prompt controls the IdP prompt behavior.
Prompt string
// AccessType controls access type.
AccessType string
// Metadata stores custom client state.
Metadata map[string]string
// UsePKCE overrides default PKCE behavior.
UsePKCE *bool
}
BeginLinkInput contains parameters for initiating an account linking ceremony.
type CompleteAuthInput ¶
type CompleteAuthInput struct {
// Provider is the identifier of the OAuth provider.
Provider string
// Code is the authorization code returned by the provider.
Code string
// State is the state parameter returned by the provider.
State string
// RedirectURI is the redirect URI supplied to the provider callback.
RedirectURI string
// Session holds optional metadata (IP address, user agent) recorded when creating the core session.
Session auth.SessionOptions
}
CompleteAuthInput contains parameters received from the provider's OAuth callback.
type CompleteLinkInput ¶
type CompleteLinkInput struct {
// Code is the authorization code returned by the provider.
Code string
// State is the state parameter returned by the provider.
State string
// RedirectURI is the callback redirect URI.
RedirectURI string
}
CompleteLinkInput contains parameters to finalize an explicit account linking flow.
type Config ¶
type Config struct {
// Providers maps provider name to its Provider implementation.
Providers map[string]provider.Provider
// StateTTL is the validity duration of newly issued OAuth state sessions.
StateTTL time.Duration
// LinkingPolicy determines whether and how accounts are linked when email addresses collide.
// Defaults to LinkingPolicyExplicitOnly (preventing unsafe automatic account linking).
LinkingPolicy LinkingPolicy
// AllowSignUp controls whether unknown OAuth users are automatically registered.
// Defaults to true.
AllowSignUp bool
// AllowOrphanUser allows unlinking a provider even if it leaves the user with no remaining auth credentials.
// Defaults to false.
AllowOrphanUser bool
// UsePKCE determines whether PKCE (RFC 7636) is generated and required by default.
// Defaults to true.
UsePKCE bool
// Hooks provides lifecycle interceptors for OAuth operations.
Hooks *Hooks
}
Config configures the OAuth plugin module.
type FailedPayload ¶
FailedPayload contains details for failed OAuth operations.
type Hooks ¶
type Hooks struct {
// contains filtered or unexported fields
}
Hooks provides lifecycle interceptors for OAuth authentication flows.
func (*Hooks) AfterOAuthSignIn ¶
func (h *Hooks) AfterOAuthSignIn(fn func(ctx context.Context, res *AuthResult) error)
AfterOAuthSignIn registers an interceptor invoked after session creation on successful sign-in.
func (*Hooks) AfterProfileFetched ¶
func (h *Hooks) AfterProfileFetched(fn func(ctx context.Context, profile *provider.ProviderProfile) error)
AfterProfileFetched registers an interceptor invoked immediately after user profile claims are parsed.
func (*Hooks) BeforeAccountLink ¶
func (h *Hooks) BeforeAccountLink(fn func(ctx context.Context, userID string, profile *provider.ProviderProfile) error)
BeforeAccountLink registers an interceptor invoked before linking a provider account to a user.
func (*Hooks) BeforeOAuthRedirect ¶
func (h *Hooks) BeforeOAuthRedirect(fn func(ctx context.Context, in *BeginAuthInput) error)
BeforeOAuthRedirect registers an interceptor invoked before building the authorization URL.
type LinkResult ¶
type LinkResult struct {
// User is the authenticated Core User who owns the linked account.
User *user.User
// Account is the newly created Core Account link.
Account *account.Account
// Profile is the normalized profile claims fetched from the provider.
Profile *provider.ProviderProfile
}
LinkResult represents the outcome of a successful explicit account linking operation.
type LinkingPolicy ¶
type LinkingPolicy string
LinkingPolicy determines how the OAuth plugin resolves collisions when an external OAuth profile presents an email address that already belongs to an existing user in Core.
const ( // LinkingPolicyExplicitOnly requires account linking to be initiated explicitly // by an authenticated user (via BeginLink/CompleteLink). // If an unlinked user with a matching email attempts OAuth sign-in, it fails with // ErrAccountLinkingRequiresConsent, preventing unsafe automatic account linking. LinkingPolicyExplicitOnly LinkingPolicy = "explicit_only" // LinkingPolicyVerifiedEmail permits automatic account linking ONLY IF: // 1. The external OAuth provider asserts profile.EmailVerified == true. // 2. The existing Core User has user.EmailVerified == true. // 3. The email addresses match. // If either email is not verified, it fails with ErrUnverifiedEmailLinkingProhibited. LinkingPolicyVerifiedEmail LinkingPolicy = "verified_email" // LinkingPolicyDisabled completely disallows account linking. If a user with the same // email already exists, it fails with ErrAccountConflict. LinkingPolicyDisabled LinkingPolicy = "disabled" )
type Module ¶
type Module struct {
// contains filtered or unexported fields
}
Module implements auth.PluginModule for GoModularAuth OAuth client authentication using plugin-sdk.
type OAuth ¶
type OAuth interface {
// BeginAuth initiates an OAuth authorization code flow for sign-in or account registration.
// It validates the redirect URI, generates state and PKCE verifier, persists state, and returns the authorization URL.
BeginAuth(ctx context.Context, in BeginAuthInput) (*BeginAuthResult, error)
// BeginLink initiates an OAuth authorization code flow specifically for linking a provider to an existing authenticated user.
// The user ID is bound to the state session to prevent CSRF and session confusion.
BeginLink(ctx context.Context, in BeginLinkInput) (*BeginAuthResult, error)
// CompleteAuth completes the OAuth flow: atomically consumes state, exchanges authorization code for tokens,
// fetches provider profile, creates or locates the user and Core Account, and creates an active Core Session.
CompleteAuth(ctx context.Context, in CompleteAuthInput) (*AuthResult, error)
// CompleteLink completes an explicit account linking flow for the user bound during BeginLink.
CompleteLink(ctx context.Context, in CompleteLinkInput) (*LinkResult, error)
// UnlinkAccount removes the link between a user and an OAuth provider.
// Fails with ErrCannotUnlinkSoleAuthMethod if this is the user's sole authentication method and orphaning is disabled.
UnlinkAccount(ctx context.Context, userID, provider string) error
// ListAccounts returns all external OAuth accounts linked to the user.
ListAccounts(ctx context.Context, userID string) ([]*account.Account, error)
// GetProvider returns a registered provider by name.
GetProvider(name string) (provider.Provider, error)
// PurgeExpired cleans up expired states from the store.
PurgeExpired(ctx context.Context) (int, error)
}
OAuth is the strongly typed capability provided by the OAuth plugin. Applications and transport adapters retrieve this capability via:
oauthAuth, err := auth.Get[plugins.OAuth](engine) // or oauthAuth := auth.MustGet[plugins.OAuth](engine)
type Option ¶
type Option func(*Config)
Option customizes a Config struct.
func WithAllowOrphanUser ¶
WithAllowOrphanUser allows unlinking an OAuth account even if no other auth credentials remain.
func WithAllowSignUp ¶
WithAllowSignUp specifies whether new user registration via OAuth is allowed.
func WithDefaultPKCE ¶
WithDefaultPKCE configures whether PKCE is enabled by default.
func WithLinkingPolicy ¶
func WithLinkingPolicy(policy LinkingPolicy) Option
WithLinkingPolicy configures the policy for resolving account linking collisions.
func WithProvider ¶
WithProvider registers a single OAuth identity provider.
func WithProviders ¶
WithProviders registers multiple OAuth identity providers.
func WithStateTTL ¶
WithStateTTL configures the lifetime of in-flight state sessions.
type PKCEPair ¶
type PKCEPair struct {
Verifier string `json:"verifier"`
Challenge string `json:"challenge"`
Method string `json:"method"`
}
PKCEPair holds the generated code verifier, challenge, and method according to RFC 7636.
func GeneratePKCE ¶
GeneratePKCE creates a cryptographically secure PKCE code verifier and S256 code challenge.
type StateCreatedPayload ¶
type StateCreatedPayload struct {
Provider string `json:"provider"`
State string `json:"state"`
Action string `json:"action"`
UserID string `json:"user_id,omitempty"`
ExpiresAt time.Time `json:"expires_at"`
}
StateCreatedPayload contains non-sensitive audit details for state creation.
type StateSession ¶
type StateSession struct {
State string `json:"state"`
Provider string `json:"provider"`
RedirectURI string `json:"redirect_uri"`
CodeVerifier string `json:"code_verifier,omitempty"`
Action Action `json:"action"`
UserID string `json:"user_id,omitempty"`
Metadata map[string]string `json:"metadata,omitempty"`
ExpiresAt time.Time `json:"expires_at"`
ConsumedAt *time.Time `json:"consumed_at,omitempty"`
CreatedAt time.Time `json:"created_at"`
}
StateSession represents an in-flight, transient OAuth state session with PKCE binding.
func (*StateSession) Consumed ¶
func (s *StateSession) Consumed() bool
Consumed reports whether the state session has already been redeemed.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
Package plugins exposes strongly-typed capability aliases for GoModularAuth plugins.
|
Package plugins exposes strongly-typed capability aliases for GoModularAuth plugins. |
|
Package provider defines the contracts and models for OAuth 2.0 / OIDC identity providers.
|
Package provider defines the contracts and models for OAuth 2.0 / OIDC identity providers. |