Documentation
¶
Overview ¶
Package social signs users in with OAuth2 / OpenID Connect providers (GitHub, Google, GitLab, Discord, Microsoft and any compliant provider), in the spirit of AdonisJS Ally, using only the standard library.
Every flow is Authorization Code + PKCE (S256). The state, PKCE verifier and OIDC nonce travel in a short-lived, HMAC-signed, HttpOnly cookie that is checked in constant time and used once.
s := social.New(app.Key.Derive("social.state", 32),
social.GitHub(social.Config{ClientID: id, ClientSecret: secret, RedirectURL: url}),
social.Google(googleCfg),
)
r.Get("/auth/{provider}/redirect", func(c *web.Ctx) error { return s.Redirect(c, c.Param("provider")) })
r.Get("/auth/{provider}/callback", func(c *web.Ctx) error {
u, err := s.User(c, c.Param("provider"))
...
})
Index ¶
- Variables
- type Config
- type Endpoints
- type OAuth2Provider
- func (p *OAuth2Provider) AuthURL(_ context.Context, _ *http.Client, state, codeChallenge, _ string) (string, error)
- func (p *OAuth2Provider) Exchange(ctx context.Context, h *http.Client, code, verifier string) (Token, error)
- func (p *OAuth2Provider) Name() string
- func (p *OAuth2Provider) User(ctx context.Context, h *http.Client, tok Token, _ string) (User, error)
- type OIDCProvider
- func (p *OIDCProvider) AuthParams(v map[string][]string) *OIDCProvider
- func (p *OIDCProvider) AuthURL(ctx context.Context, h *http.Client, state, codeChallenge, nonce string) (string, error)
- func (p *OIDCProvider) Exchange(ctx context.Context, h *http.Client, code, verifier string) (Token, error)
- func (p *OIDCProvider) Name() string
- func (p *OIDCProvider) User(ctx context.Context, h *http.Client, tok Token, nonce string) (User, error)
- type Option
- type Provider
- type Social
- type Token
- type User
Constants ¶
This section is empty.
Variables ¶
var ( ErrUnknownProvider = &errs.HTTPError{Status: http.StatusNotFound, Message: "Unknown sign-in provider."} ErrState = &errs.HTTPError{ Status: http.StatusBadRequest, Message: "The sign-in attempt expired or is invalid. Please try again.", } ErrAccessDenied = &errs.HTTPError{Status: http.StatusForbidden, Message: "Sign-in was cancelled."} )
Errors returned by the callback, mapped to HTTP statuses.
var ErrIDToken = errors.New("social: invalid ID token")
ErrIDToken is wrapped by every ID token verification failure.
Functions ¶
This section is empty.
Types ¶
type Config ¶
type Config struct {
ClientID string
ClientSecret string
RedirectURL string
// Scopes replace the provider defaults when set.
Scopes []string
}
Config holds a provider's client credentials. RedirectURL is fixed by configuration and never taken from the request.
type Endpoints ¶
type Endpoints struct {
Auth string
Token string
// API is the base of profile/userinfo calls.
API string
}
Endpoints are an OAuth2 provider's URLs.
type OAuth2Provider ¶
type OAuth2Provider struct {
// contains filtered or unexported fields
}
OAuth2Provider is a plain OAuth2 provider; the built-ins (GitHub, GitLab, Discord) and OAuth2 for anything else are values of it.
func Discord ¶
func Discord(cfg Config, opts ...Option) *OAuth2Provider
Discord signs in with Discord (scopes identify, email).
func GitHub ¶
func GitHub(cfg Config, opts ...Option) *OAuth2Provider
GitHub signs in with GitHub (scopes read:user, user:email). The email is the primary verified address from /user/emails.
func GitLab ¶
func GitLab(cfg Config, opts ...Option) *OAuth2Provider
GitLab signs in with GitLab.com (or a self-hosted instance via WithEndpoints). The primary email is confirmed when confirmed_at is set.
func OAuth2 ¶
func OAuth2(name string, cfg Config, ep Endpoints, scopes []string, mapUser func(ctx context.Context, h *http.Client, ep Endpoints, tok Token) (User, error), ) *OAuth2Provider
OAuth2 builds a provider for any OAuth2 server; mapUser loads the profile with the access token.
func (*OAuth2Provider) AuthURL ¶
func (p *OAuth2Provider) AuthURL(_ context.Context, _ *http.Client, state, codeChallenge, _ string) (string, error)
AuthURL implements Provider.
type OIDCProvider ¶
type OIDCProvider struct {
// contains filtered or unexported fields
}
OIDCProvider is an OpenID Connect provider: endpoints come from the issuer's discovery document and the ID token is verified (signature via JWKS with RS256/ES256 only, iss, aud, exp, iat, nonce).
func Microsoft ¶
func Microsoft(tenant string, cfg Config) *OIDCProvider
Microsoft signs in with Microsoft Entra ID (OIDC). tenant is "common", "organizations", "consumers" or a tenant id. Microsoft's email claim is not verified unless the xms_edov claim is true.
func OIDC ¶
func OIDC(name, issuer string, cfg Config) *OIDCProvider
OIDC builds a provider for any OpenID Connect issuer ("https://accounts.example.com"); name is the URL segment.
func (*OIDCProvider) AuthParams ¶
func (p *OIDCProvider) AuthParams(v map[string][]string) *OIDCProvider
AuthParams adds authorization URL parameters (e.g. prompt=select_account).
func (*OIDCProvider) AuthURL ¶
func (p *OIDCProvider) AuthURL( ctx context.Context, h *http.Client, state, codeChallenge, nonce string, ) (string, error)
AuthURL implements Provider.
type Option ¶
type Option func(*OAuth2Provider)
Option customizes a built-in provider.
func WithAuthParams ¶
WithAuthParams adds authorization URL parameters (e.g. prompt=consent).
func WithEndpoints ¶
WithEndpoints overrides URLs (GitHub Enterprise, self-hosted GitLab, tests).
type Provider ¶
type Provider interface {
// Name is the URL segment ("github").
Name() string
// AuthURL is the authorization endpoint URL for this attempt.
AuthURL(ctx context.Context, h *http.Client, state, challenge, nonce string) (string, error)
// Exchange trades the code for tokens.
Exchange(ctx context.Context, h *http.Client, code, verifier string) (Token, error)
// User loads the identity; nonce is the expected OIDC nonce ("" in
// stateless mode).
User(ctx context.Context, h *http.Client, tok Token, nonce string) (User, error)
}
Provider is one OAuth2/OIDC provider.
type Social ¶
type Social struct {
// HTTP is the client for provider calls (timeouts by default).
HTTP *http.Client
// StateTTL bounds the time between redirect and callback.
StateTTL time.Duration
// InsecureCookies drops the Secure flag (plain-HTTP development only).
InsecureCookies bool
// contains filtered or unexported fields
}
Social is the set of configured providers.
func New ¶
New returns Social with providers; key signs the state cookie (derive it from APP_KEY: app.Key.Derive("social.state", 32)).
func (*Social) Redirect ¶
Redirect starts sign-in with provider: it stores state, PKCE verifier and nonce in a signed cookie and redirects to the provider.
func (*Social) User ¶
User completes sign-in: it checks the state cookie (single use), handles provider errors, exchanges the code with the PKCE verifier and loads the user (verifying the ID token for OIDC providers).
func (*Social) UserFromToken ¶
UserFromToken loads the user for an access token obtained elsewhere (stateless API/SPA flows). OIDC ID tokens are not available here, so only the userinfo/profile endpoint is used.
type Token ¶
type Token struct {
Access string `json:"access_token"`
Refresh string `json:"refresh_token,omitempty"`
Expiry time.Time `json:"expiry,omitzero"`
Scopes []string `json:"scopes,omitempty"`
IDToken string `json:"-"`
}
Token is the provider's token response.
type User ¶
type User struct {
Provider string `json:"provider"`
ID string `json:"id"`
Email string `json:"email"`
EmailVerified bool `json:"email_verified"`
Name string `json:"name"`
Nickname string `json:"nickname"`
AvatarURL string `json:"avatar_url"`
Token Token `json:"-"`
Raw map[string]any `json:"-"`
}
User is the signed-in identity. EmailVerified is true only when the provider vouches for the address; link accounts by (Provider, ID), and by Email only when EmailVerified.