# modules/auth/social

```go
import "apistock.dev/modules/auth/social"
```

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](https://pkg.go.dev/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](#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](#ErrInvalidConfig).

#### func NewGoogle

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

NewGoogle returns the Google provider. It returns [ErrInvalidConfig](#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](#ErrInvalidToken), or [ErrInvalidConfig](#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](#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](#ErrWebUnavailable), [ErrExchange](#ErrExchange) or [ErrInvalidToken](#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](#ErrExchange) or [ErrInvalidConfig](#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](#MaxTokenAge), and nonce. It returns [ErrInvalidToken](#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.

