Documentation
¶
Overview ¶
Package oauthclient is SystemForge's single sanctioned package for talking to upstream social-login providers (GitHub, Google) and to SystemAuth as an OAuth client. It provides provider configuration, authorization-code exchange, normalized user-profile fetching (including verified-email detection), and CSRF state handling (cookie-bound StateManager and a pluggable server-side StateStore).
The SystemAuth server builds its GitHub/Google login on top of this package; applications should federate to SystemAuth rather than wiring social login themselves.
Index ¶
- Constants
- Variables
- func GenerateState() (string, error)
- func GitHubConfig(cfg ProviderConfig) *oauth2.Config
- func GoogleConfig(cfg ProviderConfig) *oauth2.Config
- type Connector
- type MemoryStateStore
- type ProviderConfig
- type StateData
- type StateManager
- type StateStore
- type SystemAuthConfig
- type User
Constants ¶
const ( // ProviderGitHub identifies GitHub. ProviderGitHub = "github" // ProviderGoogle identifies Google. ProviderGoogle = "google" // ProviderSystemAuth identifies a SystemAuth server. ProviderSystemAuth = "systemauth" )
Provider names used in User.Provider and StateData.Provider.
const ( // DefaultGitHubAPIURL is the GitHub REST API base URL. DefaultGitHubAPIURL = "https://api.github.com" // DefaultGoogleUserInfoURL is Google's OpenID Connect userinfo endpoint. DefaultGoogleUserInfoURL = "https://www.googleapis.com/oauth2/v3/userinfo" )
const ( // StateCookieName is the default name for the OAuth state cookie. StateCookieName = "oauth_state" // StateCookieMaxAge is the default max age for the state cookie (5 minutes). StateCookieMaxAge = 5 * 60 )
Variables ¶
var ErrInvalidState = errors.New("oauthclient: invalid or expired state")
ErrInvalidState is returned when an OAuth state value is unknown, already used, or expired.
var ErrUnsupportedProvider = errors.New("oauthclient: unsupported provider")
ErrUnsupportedProvider is returned when a Connector names a provider this package cannot fetch profiles from.
Functions ¶
func GenerateState ¶
GenerateState generates a cryptographically secure random state string.
func GitHubConfig ¶
func GitHubConfig(cfg ProviderConfig) *oauth2.Config
GitHubConfig creates an OAuth2 config for GitHub.
func GoogleConfig ¶
func GoogleConfig(cfg ProviderConfig) *oauth2.Config
GoogleConfig creates an OAuth2 config for Google.
Types ¶
type Connector ¶ added in v0.12.0
type Connector struct {
// Provider is ProviderGitHub or ProviderGoogle.
Provider string
// OAuth2 is the client configuration (endpoints, credentials, scopes).
OAuth2 *oauth2.Config
// APIURL is the GitHub API base URL (for ProviderGitHub) or the userinfo
// endpoint URL (for ProviderGoogle).
APIURL string
// HTTPClient, if set, is used for the token exchange and profile calls.
HTTPClient *http.Client
}
Connector bundles everything needed to run an authorization-code login against one upstream provider: the OAuth2 client config, the profile API location, and the HTTP client used for both. Endpoints are fields so tests (and GitHub Enterprise / alternate Google hosts) can point them elsewhere.
func NewGitHubConnector ¶ added in v0.12.0
func NewGitHubConnector(cfg ProviderConfig) *Connector
NewGitHubConnector returns a Connector for github.com.
func NewGoogleConnector ¶ added in v0.12.0
func NewGoogleConnector(cfg ProviderConfig) *Connector
NewGoogleConnector returns a Connector for Google.
func (*Connector) AuthCodeURL ¶ added in v0.12.0
func (c *Connector) AuthCodeURL(state string, opts ...oauth2.AuthCodeOption) string
AuthCodeURL returns the provider authorization URL for state.
type MemoryStateStore ¶ added in v0.12.0
type MemoryStateStore struct {
// contains filtered or unexported fields
}
MemoryStateStore is a concurrency-safe, in-memory StateStore.
func NewMemoryStateStore ¶ added in v0.12.0
func NewMemoryStateStore() *MemoryStateStore
NewMemoryStateStore creates an empty in-memory state store.
type ProviderConfig ¶
type ProviderConfig struct {
ClientID string
ClientSecret string //nolint:gosec // G117: config field, not a hardcoded secret
RedirectURL string
Scopes []string
}
ProviderConfig holds OAuth configuration for a provider.
func (ProviderConfig) Enabled ¶
func (c ProviderConfig) Enabled() bool
Enabled returns true if the provider is configured.
type StateData ¶ added in v0.12.0
type StateData struct {
// Provider is the provider the flow was started for.
Provider string `json:"provider"`
// RedirectURL is the (already validated) post-login destination.
RedirectURL string `json:"redirect_url,omitempty"`
// Nonce is an optional OpenID Connect nonce.
Nonce string `json:"nonce,omitempty"`
// PKCEVerifier is the PKCE code verifier for the token exchange.
PKCEVerifier string `json:"pkce_verifier,omitempty"`
}
StateData is the server-side record associated with an OAuth state value.
type StateManager ¶
type StateManager struct {
CookieName string
MaxAge int
Secure bool // Secure flag for cookies (default: true, requires HTTPS)
SameSite http.SameSite
}
StateManager handles OAuth state cookie management.
func NewStateManager ¶
func NewStateManager() *StateManager
NewStateManager creates a state manager with secure defaults. Cookies are set with Secure: true, requiring HTTPS. For local development over HTTP, use NewStateManagerInsecure().
func NewStateManagerInsecure ¶
func NewStateManagerInsecure() *StateManager
NewStateManagerInsecure creates a state manager for local development over HTTP. WARNING: Only use this for local development. Never use in production.
func (*StateManager) SetStateCookie ¶
func (m *StateManager) SetStateCookie(w http.ResponseWriter, state string)
SetStateCookie sets the OAuth state cookie.
func (*StateManager) ValidateState ¶
func (m *StateManager) ValidateState(w http.ResponseWriter, r *http.Request, state string) bool
ValidateState validates the OAuth state against the cookie and clears it. Returns true if valid, false otherwise.
type StateStore ¶ added in v0.12.0
type StateStore interface {
// Put stores data under state for ttl.
Put(ctx context.Context, state string, data StateData, ttl time.Duration) error
// Take returns and deletes the data for state. It returns ErrInvalidState
// when the state is unknown or expired.
Take(ctx context.Context, state string) (StateData, error)
}
StateStore persists OAuth state server-side between the login redirect and the callback. Implementations must make Take single-use.
The in-memory implementation only works for a single server instance; use a shared store (Redis, database) when running more than one replica.
type SystemAuthConfig ¶ added in v0.11.0
type SystemAuthConfig struct {
ProviderConfig
BaseURL string // SystemAuth server base URL
}
SystemAuthConfig holds SystemAuth OAuth configuration.
func (SystemAuthConfig) AuthorizationURL ¶ added in v0.11.0
func (c SystemAuthConfig) AuthorizationURL() string
AuthorizationURL returns the SystemAuth authorization endpoint.
func (SystemAuthConfig) OAuth2Config ¶ added in v0.11.0
func (c SystemAuthConfig) OAuth2Config() *oauth2.Config
OAuth2Config creates an OAuth2 config for SystemAuth.
func (SystemAuthConfig) TokenURL ¶ added in v0.11.0
func (c SystemAuthConfig) TokenURL() string
TokenURL returns the SystemAuth token endpoint.
func (SystemAuthConfig) UserInfoURL ¶ added in v0.11.0
func (c SystemAuthConfig) UserInfoURL() string
UserInfoURL returns the SystemAuth userinfo endpoint.
type User ¶
type User struct {
// ProviderID is the unique identifier from the OAuth provider.
ProviderID string `json:"provider_id"`
// Provider is the name of the OAuth provider (google, github, etc.).
Provider string `json:"provider"`
// Email is the user's email address.
Email string `json:"email"`
// EmailVerified reports whether the provider asserts that the user
// controls Email. Only a verified email may be used to link an upstream
// identity to an existing account.
EmailVerified bool `json:"email_verified"`
// Name is the user's display name.
Name string `json:"name"`
// AvatarURL is the URL to the user's profile picture.
AvatarURL string `json:"avatar_url,omitempty"`
// Username is the user's username (primarily for GitHub).
Username string `json:"username,omitempty"`
// AccessToken is the OAuth access token.
AccessToken string `json:"-"`
// RefreshToken is the OAuth refresh token (if provided).
RefreshToken string `json:"-"`
// TokenExpiry is when the access token expires.
TokenExpiry time.Time `json:"-"`
// Raw contains the raw user data from the provider.
Raw map[string]any `json:"raw,omitempty"`
}
User represents user information from an OAuth provider.
func FetchGitHubUser ¶
FetchGitHubUser fetches user info from GitHub using an authorization code.
func FetchGoogleUser ¶
FetchGoogleUser fetches user info from Google using an authorization code.
func FetchSystemAuthUser ¶ added in v0.11.0
func FetchSystemAuthUser(ctx context.Context, cfg SystemAuthConfig, accessToken string) (*User, error)
FetchSystemAuthUser fetches user info from SystemAuth using an access token.