apistockdocs
v0.4 GitHub apistock.dev
Technical/Module packages

modules/auth/social

import "apistock.dev/modules/auth/social"Source on GitHub

Package social signs people in with Google and Apple (ADR-0046): the web authorization code flow with state, nonce and PKCE, ID tokens from native apps checked against the app's client IDs, and Apple's client secret, token revocation and server-to-server notifications. 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: pre-1.0 (ADR-0015).

Constants#

const NotificationEmailDisabled, …#

go
const (
	NotificationEmailDisabled  = "email-disabled"
	NotificationEmailEnabled   = "email-enabled"
	NotificationConsentRevoked = "consent-revoked"
	NotificationAccountDelete  = "account-delete"
)

Apple server-to-server notification types.

const Google, …#

go
const (
	Google = "google"
	Apple  = "apple"
)

Provider names.

const MaxTokenAge#

go
const (
	// MaxTokenAge is how old an ID token can be when it's verified.
	MaxTokenAge = 10 * time.Minute
)

Variables#

var ErrInvalidConfig, …#

go
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 reports a provider configured only for native apps.
	ErrWebUnavailable = errors.New("social: web sign-in is not configured")
)

Errors returned by the package. Check them with errors.Is.

Functions#

func NewPKCEVerifier#

go
func NewPKCEVerifier() string

NewPKCEVerifier returns a random PKCE code verifier to keep with a web sign-in's state.

func ParseApplePrivateKey#

go
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#

go
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#

go
type Endpoints struct {
	AuthURL   string
	TokenURL  string
	KeysURL   string
	RevokeURL string
	// Issuers are the accepted "iss" values of ID tokens.
	Issuers []string
}

Endpoints are a provider's URLs. Zero values use Google's or Apple's; tests point them at socialtest.

func AppleEndpoints#

go
func AppleEndpoints() Endpoints

AppleEndpoints returns Apple's endpoints.

func GoogleEndpoints#

go
func GoogleEndpoints() Endpoints

GoogleEndpoints returns Google's endpoints.

type GoogleConfig#

go
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#

go
type Identity struct {
	// Provider is Google or Apple.
	Provider string
	// Subject identifies the person at the provider; it never changes.
	Subject string
	Email   string
	// EmailVerified reports that the provider checked the person owns Email.
	EmailVerified bool
	// PrivateEmail reports an Apple relay address.
	PrivateEmail bool
	// Name is the person's name, when the provider sends it.
	Name string
	// Audience is the client ID the token was issued for.
	Audience string
}

Identity is a person as a verified ID token describes them.

type Notification#

go
type Notification struct {
	// Type is one of the Notification constants.
	Type    string
	Subject string
	Email   string
	// PrivateEmail reports an Apple relay address.
	PrivateEmail bool
	At           time.Time
}

Notification is an Apple server-to-server notification about a person who signed in with Apple.

type Provider#

go
type Provider struct {
	// contains filtered or unexported fields
}

Provider runs one provider's sign-ins. It is safe for concurrent use.

func NewApple#

go
func NewApple(c AppleConfig) (*Provider, error)

NewApple returns the Apple provider. It returns ErrInvalidConfig.

func NewGoogle#

go
func NewGoogle(c GoogleConfig) (*Provider, error)

NewGoogle returns the Google provider. It returns ErrInvalidConfig.

func (*Provider) AppleNotification#

go
func (p *Provider) AppleNotification(ctx context.Context, payload string) (Notification, error)

AppleNotification verifies the payload Apple posts to the notification endpoint: Apple's signature, issuer and a configured audience. It returns ErrInvalidToken, or ErrInvalidConfig on a provider other than Apple.

func (*Provider) AuthCodeURL#

go
func (p *Provider) AuthCodeURL(redirectURL, state, nonce, verifier string) string

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).

func (*Provider) Exchange#

go
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. It returns ErrWebUnavailable, ErrExchange or ErrInvalidToken.

func (*Provider) ExchangeNativeCode#

go
func (p *Provider) ExchangeNativeCode(ctx context.Context, code, clientID string) (string, error)

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 or ErrInvalidConfig for a client ID that isn't configured.

func (*Provider) Name#

go
func (p *Provider) Name() string

Name returns the provider's name: Google or Apple.

func (*Provider) NativeClients#

go
func (p *Provider) NativeClients() []string

NativeClients returns the client IDs native apps' tokens may be issued for, other than the web client.

func (*Provider) Revoke#

go
func (p *Provider) Revoke(ctx context.Context, refreshToken, clientID string) error

Revoke revokes a refresh token issued for clientID, as Apple requires when an account is deleted.

func (*Provider) VerifyIDToken#

go
func (p *Provider) VerifyIDToken(ctx context.Context, rawIDToken, nonce string) (Identity, error)

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.

func (*Provider) Web#

go
func (p *Provider) Web() bool

Web reports whether the web flow is configured.

type Token#

go
type Token struct {
	Identity Identity
	// RefreshToken is set when the provider returns one (Apple); store it
	// encrypted to revoke it later.
	RefreshToken string
}

Token is the result of a code exchange.

v0.4
esc
↑↓ move↵ openesc close