oidc

package
v1.19.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 26, 2026 License: MIT Imports: 17 Imported by: 0

Documentation

Overview

Package oidc verifies OpenID Connect ID tokens from Google, Apple and Microsoft.

A client (iOS, Android, web) signs in with the provider's SDK and posts the ID token to the application, which calls Verify before trusting the token's subject and email. Verify checks the RS256 signature with github.com/go-jose/go-jose, then the expiry, issuer, audience and nonce, handling the provider quirks (Microsoft's multi-tenant issuer, Apple's string booleans), and returns a normalized Identity. What the application does with the identity is up to it.

Signing keys are fetched and cached by this package so the JWKS "issuer" field that Microsoft requires checking is honored: a key that carries an issuer only signs tokens whose iss equals it after "{tenantid}" is replaced by the token's tid. Keys without an issuer, which is all of Google's and Apple's, sign for any issuer.

The nonce check only protects against replay when the application issues the nonce, stores it and consumes it once before calling Verify. A nonce the client made up and sent along with the token proves nothing, because whoever holds a leaked token can read its nonce claim and send it. Verify can only compare; it cannot enforce single use.

Discovery and the key set are fetched lazily, the first time a provider's Verify meets a token whose key is not cached. A fetched set serves for 24 hours, then the next Verify starts a refresh behind it without waiting, so a key the provider removed stops verifying once that refresh lands: within a day and a fetch under steady traffic, while a service with no sign-ins for days serves the first token after the quiet period from the cache. A token naming a kid the set does not publish waits for a fetch, at most one a minute. A failure is not cached: the calls waiting on that fetch share its error, the next call after the minute tries again, cached keys keep serving for up to 7 days meanwhile, and Config.OnFetchError hears about each failure so the outage is seen before that. Errors are ez.EINVALID for a bad call, ez.ENOTAUTHENTICATED for a token that does not verify, ez.EUNAVAILABLE when the provider does not answer and ez.EINTERNAL when it answers a document that cannot be used, so an outage never reads as an unknown account.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Config

type Config struct {
	Google    ProviderConfig
	Apple     ProviderConfig
	Microsoft ProviderConfig
	// HTTPClient is used for discovery and key fetching. The default has a
	// 10 second timeout. A fetch runs detached from the Verify call that
	// started it and is capped at 30 seconds regardless of the client.
	HTTPClient *http.Client
	// OnFetchError, when set, is called with each discovery or key fetch
	// failure, from the fetch's own goroutine. Verify keeps serving cached
	// keys through failures for up to 7 days without reporting them, so
	// log or report them here to see an outage before sign-ins start
	// failing.
	OnFetchError func(provider Provider, err error)
}

Config enables providers. A provider with no ClientIDs is disabled.

type Identity

type Identity struct {
	Provider      Provider
	Subject       string // the provider's stable account id ("sub")
	Email         string // empty when the token carries none
	EmailVerified bool   // Google and Apple email_verified, always false for Microsoft
	PrivateEmail  bool   // Apple "Hide My Email" relay address
	HostedDomain  string // Google Workspace domain ("hd"), empty for personal accounts and other providers
	Issuer        string // the token's issuer, for logging
	Audience      string // the matched client id
}

Identity is the verified, normalized content of an ID token.

type Provider

type Provider string

Provider names an identity provider.

const (
	Google    Provider = "google"
	Apple     Provider = "apple"
	Microsoft Provider = "microsoft"
)

type ProviderConfig

type ProviderConfig struct {
	// ClientIDs are the accepted audiences: one per client app (iOS, Android, web). An
	// empty list disables the provider, and Verify answers ez.EINVALID for it.
	ClientIDs []string
	// Issuer overrides the provider's default issuer URL. For tests and private
	// deployments. The default is the provider's public issuer. Google's
	// scheme-less "accounts.google.com" is accepted only with the default issuer.
	// For Microsoft, Issuer can only be set together with a tenant id; for a
	// private or sovereign cloud set Tenant to the tenant id and Issuer to its URL.
	Issuer string
	// Tenant is Microsoft only: "common" (default), "consumers", "organizations" or a
	// tenant id, case-insensitive. Ignored for the other providers.
	// "consumers" accepts only personal accounts and "organizations" only work or
	// school accounts, while "common" accepts both.
	Tenant string
	// AllowMissingNonce accepts a token with no nonce claim when Verify is called with an
	// empty nonce. Default false: a missing nonce is ez.ENOTAUTHENTICATED. Microsoft's
	// MSAL libraries manage the nonce themselves, so applications set this for Microsoft.
	// Without a nonce any token the provider signed for one of the ClientIDs is a
	// sign-in, so Verify refuses Microsoft access tokens outright (see Verify).
	// Prefer a nonce where the client library takes one, and keep the sign-in
	// app registration from exposing an API.
	AllowMissingNonce bool
}

ProviderConfig configures one provider.

type Verifier

type Verifier struct {
	// contains filtered or unexported fields
}

Verifier verifies ID tokens. It is safe for concurrent use.

func New

func New(cfg Config) (*Verifier, error)

New validates cfg and returns a Verifier. It makes no network call. It returns ez.EINVALID when no provider is enabled, when a client id is empty, when an issuer is not an absolute http(s) URL or when the Microsoft tenant is not valid.

func (*Verifier) Verify

func (v *Verifier) Verify(ctx context.Context, provider Provider, idToken, nonce string) (Identity, error)

Verify checks an ID token from the given provider and returns the normalized identity. nonce is the value the application issued for this sign-in (see the package doc). When it is not empty the token's nonce claim must equal it or its SHA-256 as lowercase hex. When it is empty the token is refused unless the provider has AllowMissingNonce.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL