Documentation
¶
Overview ¶
Package social signs people in with Google, Apple (ADR-0046) and GitHub (ADR-0059): the web authorization code flow with state, nonce and PKCE, ID tokens from native apps checked against the app's client IDs, Apple's client secret, token revocation and server-to-server notifications, and GitHub's user and email API for a provider without OpenID Connect. It wraps golang.org/x/oauth2 and github.com/coreos/go-oidc, so apps never import their types.
The app keeps the state, nonce and PKCE verifier of a web sign-in on the server, and resolves the returned Identity to an account.
Stability: stable (ADR-0015, ADR-0054).
Index ¶
- Constants
- Variables
- func NewPKCEVerifier() string
- func ParseApplePrivateKey(pemBytes []byte) (*ecdsa.PrivateKey, error)
- type AppleConfig
- type Endpoints
- type GitHubConfig
- type GoogleConfig
- type Identity
- type Notification
- type Provider
- func (p *Provider) AppleNotification(ctx context.Context, payload string) (Notification, error)
- func (p *Provider) AuthCodeURL(redirectURL, state, nonce, verifier string) string
- func (p *Provider) Exchange(ctx context.Context, redirectURL, code, verifier, nonce string) (Token, error)
- func (p *Provider) ExchangeNativeCode(ctx context.Context, code, clientID string) (string, error)
- func (p *Provider) Name() string
- func (p *Provider) NativeClients() []string
- func (p *Provider) Revoke(ctx context.Context, refreshToken, clientID string) error
- func (p *Provider) VerifyIDToken(ctx context.Context, rawIDToken, nonce string) (Identity, error)
- func (p *Provider) Web() bool
- type Token
Constants ¶
const ( NotificationEmailDisabled = "email-disabled" NotificationEmailEnabled = "email-enabled" NotificationConsentRevoked = "consent-revoked" NotificationAccountDelete = "account-delete" )
Apple server-to-server notification types.
const ( Google = "google" Apple = "apple" GitHub = "github" )
Provider names.
const MaxNotificationAge = time.Hour
MaxNotificationAge is how old an Apple notification can be when it's verified, so an old payload can't be replayed later.
const ( // MaxTokenAge is how old an ID token can be when it's verified. MaxTokenAge = 10 * time.Minute )
Variables ¶
var ( // ErrInvalidConfig reports a configuration that can't be used. ErrInvalidConfig = errors.New("social: invalid configuration") // ErrInvalidToken reports an ID token or notification that fails // verification: signature, issuer, audience, nonce, age or claims. ErrInvalidToken = errors.New("social: invalid ID token") // ErrExchange reports an authorization code the provider refused, or a // provider that couldn't be reached. ErrExchange = errors.New("social: authorization code exchange failed") ErrWebUnavailable = errors.New("social: web sign-in is not configured") // ErrNotSupported reports an operation the provider doesn't offer, such // as verifying an ID token from GitHub, which issues none. ErrNotSupported = errors.New("social: not supported by this provider") )
Errors returned by the package. Check them with errors.Is.
Functions ¶
func NewPKCEVerifier ¶
func NewPKCEVerifier() string
NewPKCEVerifier returns a random PKCE code verifier to keep with a web sign-in's state.
func ParseApplePrivateKey ¶
func ParseApplePrivateKey(pemBytes []byte) (*ecdsa.PrivateKey, error)
ParseApplePrivateKey reads a Sign in with Apple .p8 key: a PEM PKCS #8 P-256 private key. It returns ErrInvalidConfig.
Types ¶
type AppleConfig ¶
type AppleConfig struct {
// TeamID, KeyID and PrivateKey sign client secrets: the Team ID, and the
// ID and .p8 key of a Sign in with Apple key.
TeamID string
KeyID string
PrivateKey *ecdsa.PrivateKey
// ServicesID is the web client; empty for native apps only.
ServicesID string
// BundleIDs are the iOS apps ID tokens may be issued for.
BundleIDs []string
Endpoints Endpoints
HTTPClient *http.Client
Now func() time.Time
}
AppleConfig configures Sign in with Apple.
type Endpoints ¶
type Endpoints struct {
AuthURL string
TokenURL string
KeysURL string
RevokeURL string
// Issuers are the accepted "iss" values of ID tokens.
Issuers []string
// APIURL is the base URL of GitHub's REST API, which returns the person
// and their email addresses; unused by other providers.
APIURL string
}
Endpoints are a provider's URLs. Zero values use Google's, Apple's or GitHub's; tests point them at socialtest.
type GitHubConfig ¶
type GitHubConfig struct {
// ClientID and ClientSecret are the OAuth app's.
ClientID string
ClientSecret string
Endpoints Endpoints
HTTPClient *http.Client
}
GitHubConfig configures GitHub sign-in with an OAuth app.
type GoogleConfig ¶
type GoogleConfig struct {
// ClientID and ClientSecret are the Web application client. Android apps
// use ClientID too.
ClientID string
ClientSecret string
// NativeClientIDs are the iOS and Android client IDs ID tokens may be
// issued for.
NativeClientIDs []string
Endpoints Endpoints
HTTPClient *http.Client
Now func() time.Time
}
GoogleConfig configures Google sign-in.
type Identity ¶
type Identity struct {
// Provider is Google, Apple or GitHub.
Provider string
// Subject identifies the person at the provider; it never changes. For
// GitHub it is the numeric user ID in decimal, not the login, which
// people can rename.
Subject string
Email string
// EmailVerified reports that the provider checked the person owns Email.
EmailVerified bool
// PrivateEmail reports an Apple relay address.
PrivateEmail bool
// HostedDomain is the Google Workspace domain of the account ("hd"),
// empty for personal Google accounts and Apple.
HostedDomain string
// Name is the person's name, when the provider sends it; for GitHub, the
// login when the profile has no name.
Name string
// Audience is the client ID the token was issued for (for GitHub, the
// OAuth app's client ID).
Audience string
}
Identity is a person as a verified ID token, or GitHub's API, describes them.
func (Identity) AuthoritativeEmail ¶
AuthoritativeEmail reports whether the provider manages Email's domain, so a verified Email still belongs to the person: Google for gmail.com, googlemail.com and the account's own Workspace domain, Apple for relay addresses and iCloud (icloud.com, me.com, mac.com). For other addresses, EmailVerified only says the person controlled the address when they added it to their provider account, possibly years ago; don't link such an identity to an existing account without the account's owner (security review AUTH-M-1). GitHub hosts no one's email, so it is never authoritative (ADR-0059).
type Notification ¶
type Notification struct {
// ID identifies the notification ("jti", or a hash of the payload when
// Apple sends none). Remember it until IssuedAt plus
// [MaxNotificationAge] and ignore a notification seen before: a replayed
// payload carries the same ID.
ID string
// Type is one of the Notification constants.
Type string
Subject string
Email string
// PrivateEmail reports an Apple relay address.
PrivateEmail bool
// At is when the event happened; IssuedAt when Apple signed the
// notification.
At time.Time
IssuedAt time.Time
}
Notification is an Apple server-to-server notification about a person who signed in with Apple.
type Provider ¶
type Provider struct {
// contains filtered or unexported fields
}
Provider runs one provider's sign-ins. It is safe for concurrent use.
func NewApple ¶
func NewApple(c AppleConfig) (*Provider, error)
NewApple returns the Apple provider. It returns ErrInvalidConfig.
func NewGitHub ¶
func NewGitHub(c GitHubConfig) (*Provider, error)
NewGitHub returns the GitHub provider (ADR-0059). GitHub has no OpenID Connect: Provider.Exchange trades the code (with state and PKCE, like Google) for an access token, reads the person from GET /user and their primary email from GET /user/emails with the scopes read:user and user:email, and forgets the token. It offers the web flow only: ID tokens, native codes and revocation return ErrNotSupported. It returns ErrInvalidConfig.
func NewGoogle ¶
func NewGoogle(c GoogleConfig) (*Provider, error)
NewGoogle returns the Google provider. It returns ErrInvalidConfig.
func (*Provider) AppleNotification ¶
AppleNotification verifies the payload Apple posts to the notification endpoint: Apple's signature, issuer, a configured audience, and an issue time within MaxNotificationAge. It returns ErrInvalidToken, or ErrInvalidConfig on a provider other than Apple.
func (*Provider) AuthCodeURL ¶
AuthCodeURL returns the provider URL that starts a web sign-in returning to redirectURL. state and nonce are single-use random values the app keeps; verifier is from NewPKCEVerifier (Apple ignores it). GitHub, which issues no ID token, ignores nonce: state and PKCE protect its flow.
func (*Provider) Exchange ¶
func (p *Provider) Exchange(ctx context.Context, redirectURL, code, verifier, nonce string) (Token, error)
Exchange trades a web sign-in's authorization code for tokens and verifies the ID token against the web client and nonce. For GitHub, it reads the person from GitHub's API with the access token instead, which it then forgets (nonce is unused). It returns ErrWebUnavailable, ErrExchange or ErrInvalidToken.
func (*Provider) ExchangeNativeCode ¶
ExchangeNativeCode trades an authorization code a native app received for clientID, such as Apple's authorizationCode on iOS, and returns the refresh token (empty when the provider sends none). It returns ErrExchange, ErrInvalidConfig for a client ID that isn't configured, or ErrNotSupported for GitHub.
func (*Provider) NativeClients ¶
NativeClients returns the client IDs native apps' tokens may be issued for, other than the web client.
func (*Provider) Revoke ¶
Revoke revokes a refresh token issued for clientID, as Apple requires when an account is deleted. It returns ErrNotSupported for GitHub, whose tokens are never kept.
func (*Provider) VerifyIDToken ¶
VerifyIDToken verifies an ID token a native app obtained: signature, issuer, an audience among the configured client IDs, expiry, an age under MaxTokenAge, and nonce. It returns ErrInvalidToken, wrapping ErrNotSupported for GitHub, which issues no ID tokens.
Directories
¶
| Path | Synopsis |
|---|---|
|
Package socialtest runs an in-process OpenID Connect provider standing in for Google or Apple in tests: it serves signing keys, a token endpoint and a revocation endpoint, and issues signed ID tokens, authorization codes and Apple notifications.
|
Package socialtest runs an in-process OpenID Connect provider standing in for Google or Apple in tests: it serves signing keys, a token endpoint and a revocation endpoint, and issues signed ID tokens, authorization codes and Apple notifications. |