Documentation
¶
Overview ¶
Package upstream provides types and implementations for upstream Identity Provider communication in the OAuth authorization server.
Architecture ¶
The package is designed around a core Provider interface that abstracts upstream IDP operations. The interface captures essential OAuth/OIDC operations without leaking implementation details:
- AuthorizationURL: Build redirect URL for user authentication
- ExchangeCode: Exchange authorization code for tokens
- RefreshTokens: Refresh expired tokens
- UserInfo: Fetch user claims
Optional Capability Interfaces ¶
Implementations may also implement optional capability interfaces for OIDC-specific features. Consumers should use type assertions to check:
if validator, ok := provider.(upstream.IDTokenNonceValidator); ok {
claims, err := validator.ValidateIDTokenWithNonce(idToken, nonce)
}
Available optional interfaces:
- IDTokenNonceValidator: OIDC nonce validation for replay protection
- UserInfoSubjectValidator: OIDC subject validation per Section 5.3.4
Type Hierarchy ¶
Provider (interface)
|
OIDCProvider (implementation)
|-- IDTokenNonceValidator (optional)
+-- UserInfoSubjectValidator (optional)
Value Objects ¶
- Tokens: Token response from upstream IDP
- UserInfo: User claims from UserInfo endpoint
- Config: Configuration for upstream IDP connection
- IDTokenClaims: Parsed claims from ID token
Usage ¶
config := &upstream.Config{
Issuer: "https://accounts.google.com",
ClientID: "your-client-id",
ClientSecret: "your-client-secret",
RedirectURI: "https://your-app.com/callback",
Scopes: []string{"openid", "email", "profile"},
}
provider, err := upstream.NewOIDCProvider(ctx, config)
if err != nil {
return err
}
// Build authorization URL
authURL, err := provider.AuthorizationURL(state, pkceChallenge, nonce)
// After callback, exchange code for tokens
tokens, err := provider.ExchangeCode(ctx, code, pkceVerifier)
Extensibility ¶
To add a new IDP type (e.g., SAML), implement the Provider interface. The optional capability interfaces can be implemented as needed.
UserInfo Extensibility ¶
The package supports flexible UserInfo fetching through the UserInfoFetcher interface and UserInfoConfig. This enables:
- Custom field mapping for non-standard provider responses
- Additional headers for provider-specific requirements
To check if a provider supports UserInfo fetching:
if fetcher, ok := provider.(upstream.UserInfoFetcher); ok {
userInfo, err := fetcher.FetchUserInfo(ctx, accessToken)
}
For custom provider configuration, use UserInfoConfig:
config := &upstream.UserInfoConfig{
EndpointURL: "https://api.example.com/user",
FieldMapping: &upstream.UserInfoFieldMapping{
SubjectField: "user_id",
},
}
Index ¶
- Variables
- type AuthorizationOption
- type BaseOAuth2Provider
- func (p *BaseOAuth2Provider) AuthorizationURL(state, codeChallenge string, opts ...AuthorizationOption) (string, error)
- func (p *BaseOAuth2Provider) ExchangeCode(ctx context.Context, code, codeVerifier string) (*Tokens, error)
- func (p *BaseOAuth2Provider) RefreshTokens(ctx context.Context, refreshToken string) (*Tokens, error)
- func (*BaseOAuth2Provider) Type() ProviderType
- type CommonOAuthConfig
- type IDTokenClaims
- type IDTokenNonceValidator
- type OAuth2Config
- type OAuth2Provider
- type OAuth2ProviderOption
- type OIDCEndpoints
- type ProviderType
- type Tokens
- type UserInfo
- type UserInfoConfig
- type UserInfoFetcher
- type UserInfoFieldMapping
- type UserInfoSubjectValidator
Constants ¶
This section is empty.
Variables ¶
var ErrUserInfoSubjectMismatch = fmt.Errorf("userinfo subject does not match expected subject")
ErrUserInfoSubjectMismatch is returned when the UserInfo endpoint returns a subject that does not match the expected subject from the ID Token. This validation is required per OIDC Core Section 5.3.4 to prevent user impersonation.
Functions ¶
This section is empty.
Types ¶
type AuthorizationOption ¶ added in v0.7.2
type AuthorizationOption func(*authorizationOptions)
AuthorizationOption configures authorization URL generation.
func WithAdditionalParams ¶ added in v0.7.2
func WithAdditionalParams(params map[string]string) AuthorizationOption
WithAdditionalParams adds custom parameters to the authorization URL.
type BaseOAuth2Provider ¶ added in v0.7.2
type BaseOAuth2Provider struct {
// contains filtered or unexported fields
}
BaseOAuth2Provider implements OAuth 2.0 flows for pure OAuth 2.0 providers. This can be used standalone for OAuth 2.0 providers without OIDC support, or embedded by OIDCProvider to share common OAuth 2.0 logic.
func NewOAuth2Provider ¶ added in v0.7.2
func NewOAuth2Provider(config *OAuth2Config, opts ...OAuth2ProviderOption) (*BaseOAuth2Provider, error)
NewOAuth2Provider creates a new pure OAuth 2.0 provider. Use this for providers that don't support OIDC discovery. The config must include AuthorizationEndpoint and TokenEndpoint.
func (*BaseOAuth2Provider) AuthorizationURL ¶ added in v0.7.2
func (p *BaseOAuth2Provider) AuthorizationURL(state, codeChallenge string, opts ...AuthorizationOption) (string, error)
AuthorizationURL builds the URL to redirect the user to the upstream IDP.
func (*BaseOAuth2Provider) ExchangeCode ¶ added in v0.7.2
func (p *BaseOAuth2Provider) ExchangeCode(ctx context.Context, code, codeVerifier string) (*Tokens, error)
ExchangeCode exchanges an authorization code for tokens with the upstream IDP.
func (*BaseOAuth2Provider) RefreshTokens ¶ added in v0.7.2
func (p *BaseOAuth2Provider) RefreshTokens(ctx context.Context, refreshToken string) (*Tokens, error)
RefreshTokens refreshes the upstream IDP tokens.
func (*BaseOAuth2Provider) Type ¶ added in v0.7.2
func (*BaseOAuth2Provider) Type() ProviderType
Type returns the provider type.
type CommonOAuthConfig ¶ added in v0.7.2
type CommonOAuthConfig struct {
// ClientID is the OAuth client ID registered with the upstream IDP.
ClientID string
// ClientSecret is the OAuth client secret registered with the upstream IDP.
// Optional for public clients (RFC 6749 Section 2.1) which authenticate using
// PKCE instead of a client secret. Required for confidential clients.
ClientSecret string
// Scopes are the OAuth scopes to request from the upstream IDP.
Scopes []string
// RedirectURI is the callback URL where the upstream IDP will redirect
// after authentication.
RedirectURI string
}
CommonOAuthConfig contains fields shared by all OAuth provider types. This provides compile-time type safety by separating OIDC and OAuth2 configuration.
func (*CommonOAuthConfig) Validate ¶ added in v0.7.2
func (c *CommonOAuthConfig) Validate() error
Validate checks that CommonOAuthConfig has all required fields.
type IDTokenClaims ¶
type IDTokenClaims struct {
// Issuer is the issuer identifier (iss claim).
Issuer string
// Subject is the subject identifier (sub claim).
Subject string
// Audience contains the audience(s) this ID Token is intended for (aud claim).
Audience []string
// ExpiresAt is the expiration time (exp claim).
ExpiresAt time.Time
// IssuedAt is the time at which the ID Token was issued (iat claim).
IssuedAt time.Time
// Nonce is the value used to associate a client session with an ID Token (nonce claim).
Nonce string
// AuthTime is the time when the end-user authentication occurred (auth_time claim).
AuthTime time.Time
// AuthorizedParty is the party to which the ID Token was issued (azp claim).
AuthorizedParty string
// Email is the user's email address.
Email string
// EmailVerified indicates whether the user's email has been verified.
EmailVerified bool
// Name is the user's full name.
Name string
// RawClaims contains all claims from the ID Token payload.
RawClaims map[string]any
}
IDTokenClaims contains the standard OIDC ID Token claims. See OIDC Core Section 2 for claim definitions.
type IDTokenNonceValidator ¶
type IDTokenNonceValidator interface {
// ValidateIDTokenWithNonce validates an ID token with nonce verification.
// Returns the parsed claims if validation succeeds, or an error if validation fails.
ValidateIDTokenWithNonce(idToken, expectedNonce string) (*IDTokenClaims, error)
}
IDTokenNonceValidator is implemented by providers that support OIDC nonce validation. This is used to validate the nonce claim in ID tokens to prevent replay attacks.
type OAuth2Config ¶ added in v0.7.2
type OAuth2Config struct {
CommonOAuthConfig
// AuthorizationEndpoint is the URL for the OAuth authorization endpoint.
AuthorizationEndpoint string
// TokenEndpoint is the URL for the OAuth token endpoint.
TokenEndpoint string
// UserInfo contains configuration for fetching user information (optional).
// When nil, the provider does not support UserInfo fetching.
UserInfo *UserInfoConfig
}
OAuth2Config contains configuration for pure OAuth 2.0 providers without OIDC discovery.
func (*OAuth2Config) Validate ¶ added in v0.7.2
func (c *OAuth2Config) Validate() error
Validate checks that OAuth2Config has all required fields.
type OAuth2Provider ¶ added in v0.7.2
type OAuth2Provider interface {
// Type returns the provider type.
Type() ProviderType
// AuthorizationURL builds the URL to redirect the user to the upstream IDP.
// state: our internal state to correlate callback
// codeChallenge: PKCE challenge to send to upstream (if supported)
// opts: optional configuration such as nonce or additional parameters
AuthorizationURL(state, codeChallenge string, opts ...AuthorizationOption) (string, error)
// ExchangeCode exchanges an authorization code for tokens with the upstream IDP.
ExchangeCode(ctx context.Context, code, codeVerifier string) (*Tokens, error)
// RefreshTokens refreshes the upstream IDP tokens.
RefreshTokens(ctx context.Context, refreshToken string) (*Tokens, error)
}
OAuth2Provider handles communication with an upstream Identity Provider. This is the base interface for all provider types.
type OAuth2ProviderOption ¶ added in v0.7.2
type OAuth2ProviderOption func(*BaseOAuth2Provider)
OAuth2ProviderOption configures a BaseOAuth2Provider.
func WithOAuth2HTTPClient ¶ added in v0.7.2
func WithOAuth2HTTPClient(client *http.Client) OAuth2ProviderOption
WithOAuth2HTTPClient sets a custom HTTP client.
type OIDCEndpoints ¶
type OIDCEndpoints struct {
// Issuer is the issuer identifier.
Issuer string `json:"issuer"`
// AuthorizationEndpoint is the URL for the authorization endpoint.
AuthorizationEndpoint string `json:"authorization_endpoint"`
// TokenEndpoint is the URL for the token endpoint.
TokenEndpoint string `json:"token_endpoint"`
// UserInfoEndpoint is the URL for the userinfo endpoint.
UserInfoEndpoint string `json:"userinfo_endpoint,omitempty"`
// JWKSEndpoint is the URL for the JWKS endpoint.
JWKSEndpoint string `json:"jwks_uri,omitempty"`
// CodeChallengeMethodsSupported lists the supported PKCE code challenge methods.
CodeChallengeMethodsSupported []string `json:"code_challenge_methods_supported,omitempty"`
}
OIDCEndpoints contains the discovered endpoints for an OIDC provider.
type ProviderType ¶ added in v0.7.2
type ProviderType string
ProviderType identifies the type of upstream Identity Provider.
const ( // ProviderTypeOAuth2 is for pure OAuth 2.0 providers with explicit endpoints. ProviderTypeOAuth2 ProviderType = "oauth2" )
type Tokens ¶
type Tokens struct {
// AccessToken is the access token from the upstream IDP.
AccessToken string
// RefreshToken is the refresh token from the upstream IDP (if provided).
RefreshToken string
// IDToken is the ID token from the upstream IDP (for OIDC).
IDToken string
// ExpiresAt is when the access token expires.
ExpiresAt time.Time
}
Tokens represents the tokens obtained from an upstream Identity Provider. This type is used for token exchange with the IDP, but stored separately (see storage.IDPTokens for the storage representation).
type UserInfo ¶
type UserInfo struct {
// Subject is the unique identifier for the user (sub claim).
Subject string `json:"sub"`
// Email is the user's email address.
Email string `json:"email,omitempty"`
// Name is the user's full name.
Name string `json:"name,omitempty"`
// Claims contains all claims returned by the userinfo endpoint.
Claims map[string]any `json:"-"`
}
UserInfo contains user information retrieved from the upstream IDP.
type UserInfoConfig ¶ added in v0.7.2
type UserInfoConfig struct {
// EndpointURL is the URL of the userinfo endpoint (required).
EndpointURL string
// HTTPMethod is the HTTP method to use (default: GET).
HTTPMethod string
// AdditionalHeaders contains extra headers to include in the request.
AdditionalHeaders map[string]string
// FieldMapping contains custom field mapping configuration.
// If nil, standard OIDC field names are used ("sub", "name", "email").
FieldMapping *UserInfoFieldMapping
}
UserInfoConfig contains configuration for fetching user information from an upstream provider. This supports both standard OIDC UserInfo endpoints and custom provider-specific endpoints. Authentication is always performed using Bearer token in the Authorization header.
func (*UserInfoConfig) Validate ¶ added in v0.7.2
func (c *UserInfoConfig) Validate() error
Validate checks that UserInfoConfig has all required fields and valid values.
type UserInfoFetcher ¶ added in v0.7.2
type UserInfoFetcher interface {
// FetchUserInfo retrieves user information using the provided access token.
// Returns the parsed UserInfo on success, or an error if the request fails
// or the response cannot be parsed.
FetchUserInfo(ctx context.Context, accessToken string) (*UserInfo, error)
}
UserInfoFetcher is implemented by providers that support fetching user information. This interface enables extensible UserInfo retrieval from various endpoint types, including standard OIDC UserInfo endpoints and custom provider-specific APIs.
Implementations may use different authentication methods, field mappings, and response formats as configured via UserInfoConfig.
type UserInfoFieldMapping ¶ added in v0.7.2
type UserInfoFieldMapping struct {
// SubjectField is the field name for the user ID (default: "sub").
SubjectField string
// NameField is the field name for the display name (default: "name").
NameField string
// EmailField is the field name for the email address (default: "email").
EmailField string
}
UserInfoFieldMapping maps provider-specific field names to standard UserInfo fields. This allows adapting non-standard provider responses to the canonical UserInfo structure.
type UserInfoSubjectValidator ¶
type UserInfoSubjectValidator interface {
// UserInfoWithSubjectValidation fetches user info and validates the subject matches expected.
// Returns ErrUserInfoSubjectMismatch if the subjects do not match.
UserInfoWithSubjectValidation(ctx context.Context, accessToken, expectedSubject string) (*UserInfo, error)
}
UserInfoSubjectValidator is implemented by providers that support UserInfo subject validation per OIDC Core Section 5.3.4. This validation ensures the UserInfo response's subject matches the ID Token's subject to prevent user impersonation attacks.