Documentation
¶
Overview ¶
Package oauth is an OAuth 2.0 authorization-code client with PKCE and OpenID Connect ID-token verification for social login. It returns a typed Profile; linking or creating the application's own user is the application's decision. Provider requests use an SSRF-restricted httpclient.Client. No dependency beyond the standard library cryptography is used.
Index ¶
Constants ¶
const DefaultPendingLifetime = 10 * time.Minute
DefaultPendingLifetime bounds the time between redirect and callback.
const Denied failureCode = "oauth authorization was denied at the provider"
Denied is the cause of an auth.Unauthenticated callback that carried a provider error such as access_denied (the user declined).
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Authorization ¶
Authorization is a started request: redirect the browser to URL and keep Pending until the callback.
func (Authorization) LogValue ¶
func (Authorization) LogValue() slog.Value
type Callback ¶
type Callback struct {
Code secret.String
State string
// Error is the provider's error code, for example access_denied.
Error string
}
Callback is the provider's redirect query.
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
Client runs one provider's authorization-code flow. It is immutable and safe for concurrent use; the JWKS cache is shared by its calls.
func NewClient ¶
NewClient validates the provider and borrows an outbound client that must restrict destinations (see Provider.Destinations), so provider URLs cannot be used to reach internal services. The client must have no BaseURL.
func (*Client) Begin ¶
func (c *Client) Begin(ctx context.Context) (Authorization, error)
Begin creates fresh state, nonce and PKCE verifier and the provider URL with response_type=code, the exact redirect URI and the S256 code challenge.
func (*Client) Complete ¶
Complete validates a callback against its pending request (provider, expiry and state), exchanges the code with the PKCE verifier and reads the profile. OpenID Connect ID tokens are verified (signature, issuer, audience, expiry, issue time and nonce). Every rejected callback returns auth.Unauthenticated; provider and network failures remain operational errors. The pending request is single use: discard it after this call, whatever the result.
type Credentials ¶
Credentials are the application's registration at a provider. RedirectURL is the exact registered callback URI; it is sent verbatim in the authorization and token requests and is never taken from an incoming request.
type Flow ¶
type Flow struct {
// contains filtered or unexported fields
}
Flow keeps the pending request in an encrypted, short-lived cookie between the redirect and the callback, so no server-side state is needed. The cookie is authenticated and scoped by the application key ring (http.CookieEncrypter), HttpOnly, Secure and SameSite=Lax (sent on the provider's top-level redirect back), and expires with the pending request.
func NewFlow ¶
func NewFlow(client *Client, encrypter http.CookieEncrypter, name http.CookieName) (*Flow, error)
NewFlow binds a client to a pending-request cookie. Use one cookie name per provider, for example "__Host-foundry_oauth_google".
func (*Flow) Finish ¶
Finish handles the provider's redirect to the registered callback: it reads and always clears the pending cookie (it is single use), validates the query and completes the flow. A missing, expired or tampered cookie, a callback on another path, a state mismatch or a provider denial return auth.Unauthenticated.
type Pending ¶
type Pending struct {
// contains filtered or unexported fields
}
Pending is the server-held half of one authorization request: the state that binds the callback to this browser, the OpenID nonce bound into the ID token and the PKCE code verifier. Keep it server-side or in an encrypted, short-lived cookie (see Flow); never in a URL or plain cookie. Routine formatting, logging and JSON redact it.
func (Pending) MarshalJSON ¶
func (Pending) Provider ¶
func (p Pending) Provider() ProviderName
Provider and ExpiresAt describe the pending request without its secrets.
type Profile ¶
type Profile struct {
Provider ProviderName
Subject string
Email string
EmailVerified bool
Name string
// Username is the provider handle when it has one (GitHub login).
Username string
AvatarURL string
// Token is the provider access for further API calls; it is redacted.
Token Token
}
Profile is the verified identity a provider asserted. Subject is the stable account identifier at the provider (the OpenID sub claim or GitHub's numeric account ID) and is the key to link on; email addresses can change and are only trustworthy when EmailVerified. Mapping a profile to the application's own user, including creating or linking one, is the application's decision.
type ProfileSource ¶
type ProfileSource uint8
ProfileSource selects how a provider's user profile is read.
const ( // OpenIDConnect verifies the ID token returned by the token endpoint // (signature against JWKSURL, issuer, audience, expiry and nonce) and reads // its standard claims. OpenIDConnect ProfileSource = iota + 1 // GitHubUser reads GitHub's REST user API with the access token, plus the // verified primary address from its emails API when that scope is granted. GitHubUser )
type Provider ¶
type Provider struct {
Name ProviderName
Credentials Credentials
Source ProfileSource
AuthorizationURL string
TokenURL string
Scopes []string
// Issuers and JWKSURL are required for OpenIDConnect.
Issuers []string
JWKSURL string
// UserURL and EmailsURL are used by GitHubUser.
UserURL string
EmailsURL string
}
Provider is an immutable provider declaration. Use a preset such as Google or GitHub, or fill the fields for another OpenID Connect provider.
func GitHub ¶
func GitHub(credentials Credentials) Provider
GitHub is the OAuth 2.0 preset using GitHub's user API (scopes read:user, user:email). GitHub issues no ID token; the numeric account ID is the Subject.
func Google ¶
func Google(credentials Credentials) Provider
Google is the OpenID Connect preset (scopes openid, email, profile).
func (Provider) Destinations ¶
func (p Provider) Destinations() (httpclient.DestinationPolicy, error)
Destinations returns an SSRF-restricted outbound policy admitting only this provider's HTTPS hosts on port 443, for the httpclient.Client passed to NewClient.
type ProviderName ¶
type ProviderName string
ProviderName identifies a configured provider, for example "google".
type Token ¶
type Token struct {
Access secret.String
Refresh value.Optional[secret.String]
ExpiresAt value.Optional[time.Time]
Scopes []string
}
Token is the provider's credential for calling its APIs on the user's behalf. Formatting, logging and JSON redact it; Access and Refresh are explicit disclosure boundaries.