Documentation
¶
Overview ¶
Package gosso implements the shared OpenID Connect login flow used by GoDash, GoCron and friends: the browser handshake, state and session cookies, PKCE S256 code exchange against a discovered provider, and pluggable session storage.
Start with Config for the issuer credentials and Auth for the Echo v5 routes and middleware. HandleCallback runs the whole callback choreography and returns either a LoginResult or a classified LoginFailure for the login page redirect; Auth.AuthorizeSubject can optionally refuse sessions for individual subjects. HMACSessions is the built-in signed-cookie SessionManager — its sessions are stateless and cannot be revoked before their expiry. Implement SessionManager to back sessions with your own store when immediate revocation matters.
Settings are read through a func() Config indirection so apps can reload configuration without rebuilding the Auth instance.
Index ¶
- Constants
- Variables
- func DefaultCookiePrefix(config Config) string
- func DefaultScopes() []string
- func RandomToken(size int) (string, error)
- func SanitizeRedirect(raw string) string
- func SetLogger(l *slog.Logger)
- func SignHMAC(key, subject string, expiresAt time.Time) string
- func ValidLoginErrorCode(raw string) bool
- func ValidateSessionKey(key string) error
- func VerifyHMAC(key, value string, now time.Time) (string, time.Time, error)
- type Auth
- func (a *Auth) Authenticate(echoContext *echo.Context) (*User, error)
- func (a *Auth) CallbackURL(c *echo.Context) string
- func (a *Auth) ClearSession(echoContext *echo.Context)
- func (a *Auth) ConsumeLoginState(echoContext *echo.Context) (state, verifier, redirect string, err error)
- func (a *Auth) Enabled() bool
- func (a *Auth) Exchange(echoContext *echo.Context, code, verifier string) (string, error)
- func (a *Auth) HandleCallback(echoContext *echo.Context) (*LoginResult, *LoginFailure)
- func (a *Auth) Middleware() echo.MiddlewareFunc
- func (a *Auth) ProviderResolve() (bool, error)
- func (a *Auth) Resolved() bool
- func (a *Auth) SessionTTL() time.Duration
- func (a *Auth) StartLogin(echoContext *echo.Context, redirect string) error
- func (a *Auth) StartSession(echoContext *echo.Context, subject string) error
- type Config
- type CookieOptions
- type HMACOptions
- type HMACSessions
- type LoginError
- type LoginFailure
- type LoginResult
- type Provider
- type SessionManager
- type User
Constants ¶
const DefaultSessionTTL = 24 * time.Hour
DefaultSessionTTL is the session lifetime used when Config.SessionTTL is not positive.
const DiscoveryTimeout = 10 * time.Second
DiscoveryTimeout bounds a single OIDC discovery attempt.
const MinSessionKeyLength = 32
MinSessionKeyLength is the shortest accepted signing key for HMACSessions.
Variables ¶
var ( // ErrInvalidIssuer is returned when IssuerURL is not an absolute URL or has a trailing slash. ErrInvalidIssuer = errors.New("sso configuration error: issuer_url must be a valid absolute URL without a trailing slash") // ErrMissingOIDCFields is returned when a required credential is empty while SSO is enabled. ErrMissingOIDCFields = errors.New("sso configuration error: issuer_url, client_id and client_secret are required when SSO is enabled") )
var ( // ErrUnauthenticated is returned when no valid session is present. ErrUnauthenticated = errors.New("not authenticated") ErrProviderUnavailable = errors.New("identity provider is not reachable") // ErrInvalidSessionKey is returned by ValidateSessionKey for short signing keys. ErrInvalidSessionKey = errors.New("session signing key must be at least 32 characters") // ErrStateMismatch is returned when the callback state does not match the login state cookie. ErrStateMismatch = errors.New("callback state does not match the login state") ErrSubjectUnauthorized = errors.New("subject is not authorized to sign in") )
var ErrInvalidSession = errors.New("invalid session cookie")
ErrInvalidSession is returned for a session cookie that is malformed, tampered with or expired.
Functions ¶
func DefaultCookiePrefix ¶ added in v1.1.0
DefaultCookiePrefix returns the cookie prefix from the config, or one derived from the ClientID.
func DefaultScopes ¶
func DefaultScopes() []string
DefaultScopes returns the scopes requested when Config.Scopes is empty.
func RandomToken ¶
RandomToken returns size cryptographically random bytes as a hex string.
func SanitizeRedirect ¶
SanitizeRedirect keeps only same-origin absolute paths and falls back to "/" for anything else. Percent-encoded and backslash variants that browsers normalize back into protocol-relative URLs, such as "/%2F%2Fevil.example.com", are rejected as well.
func SetLogger ¶
SetLogger replaces the package logger used for discovery diagnostics. A nil logger is ignored.
func SignHMAC ¶
SignHMAC returns the base64url payload and HMAC-SHA256 signature for subject and expiresAt.
func ValidLoginErrorCode ¶
ValidLoginErrorCode reports whether raw is one of the known LoginError codes.
func ValidateSessionKey ¶
ValidateSessionKey reports ErrInvalidSessionKey when key is shorter than MinSessionKeyLength.
Types ¶
type Auth ¶
type Auth struct {
Sessions SessionManager
Settings func() Config
CallbackPath string
LoginPath string
// AuthorizeSubject optionally gates logins: when it returns false for the verified
// subject, the callback fails with LoginErrorRejected before a session is started.
AuthorizeSubject func(subject string) bool
// contains filtered or unexported fields
}
Auth runs the Echo v5 login lifecycle and the session middleware for a single app.
func New ¶
func New(settings func() Config, sessions SessionManager, callbackPath, loginPath string) *Auth
New wires an Auth to settings and a session store. Enabled settings warm provider discovery in the background.
func (*Auth) Authenticate ¶
Authenticate resolves the current user from the session store.
func (*Auth) CallbackURL ¶
CallbackURL returns the redirect URI registered with the provider for this request.
func (*Auth) ClearSession ¶
ClearSession removes the local session, without contacting the provider.
func (*Auth) ConsumeLoginState ¶
func (a *Auth) ConsumeLoginState(echoContext *echo.Context) (state, verifier, redirect string, err error)
ConsumeLoginState validates and clears the state cookie and returns the state, PKCE verifier and redirect target. The cookie is cleared before it is read on purpose: one-shot semantics come from the response expiring it, while the request copy stays readable for this handler.
func (*Auth) Exchange ¶
Exchange redeems the authorization code and returns the verified subject of the id_token.
func (*Auth) HandleCallback ¶ added in v1.1.0
func (a *Auth) HandleCallback(echoContext *echo.Context) (*LoginResult, *LoginFailure)
HandleCallback finishes the OIDC login for a callback request: it rejects provider-reported errors, consumes and checks the state cookie, exchanges the code, applies AuthorizeSubject and starts the session. It returns the login result or a classified failure for the login page redirect.
func (*Auth) Middleware ¶
func (a *Auth) Middleware() echo.MiddlewareFunc
Middleware redirects unauthenticated requests to LoginPath, or answers 401 when no login path is set.
func (*Auth) ProviderResolve ¶
ProviderResolve resolves the provider now and reports whether discovery succeeded.
func (*Auth) Resolved ¶
Resolved reports whether provider discovery has already completed successfully.
func (*Auth) SessionTTL ¶
SessionTTL returns the configured session lifetime, falling back to DefaultSessionTTL.
func (*Auth) StartLogin ¶
StartLogin writes the state cookie and redirects the browser to the provider.
type Config ¶
type Config struct {
IssuerURL string
ClientID string
ClientSecret string
SessionKey string
SessionTTL time.Duration
CookieSecure bool
AppURL string
Scopes []string
CookiePrefix string
Enabled bool
}
Config holds the OpenID Connect settings shared by all apps using this package.
func (Config) EffectiveSessionTTL ¶ added in v1.1.0
EffectiveSessionTTL returns SessionTTL, falling back to DefaultSessionTTL when it is not positive.
func (Config) Validate ¶
Validate reports whether the config carries usable issuer credentials and, when set, a parsable AppURL.
func (Config) WithDefaults ¶
WithDefaults returns a copy with SessionTTL and Scopes filled in when they are empty.
type CookieOptions ¶
type CookieOptions struct {
Secure func() bool
}
CookieOptions builds the HttpOnly, SameSite=Lax cookies shared by the session implementations.
type HMACOptions ¶
HMACOptions configures NewHMACSessions. CookieName takes precedence over Prefix.
type HMACSessions ¶
type HMACSessions struct {
// contains filtered or unexported fields
}
HMACSessions is a SessionManager backed by a signed, stateless cookie.
func NewHMACSessions ¶
func NewHMACSessions(opts HMACOptions) *HMACSessions
NewHMACSessions returns the cookie name from opts.CookieName, or opts.Prefix with "_session" appended.
func (*HMACSessions) Authenticate ¶
func (h *HMACSessions) Authenticate(echoContext *echo.Context) (*User, error)
Authenticate verifies the session cookie and refreshes it once half the TTL has passed. Sessions are stateless by design: they cannot be revoked before their expiry, so back them with a custom SessionManager when immediate revocation matters.
func (*HMACSessions) Clear ¶
func (h *HMACSessions) Clear(echoContext *echo.Context) error
Clear expires the session cookie.
func (*HMACSessions) CookieName ¶
func (h *HMACSessions) CookieName() string
CookieName returns the name of the session cookie.
type LoginError ¶
type LoginError string
LoginError is the stable code an app redirects to its login page with.
const ( // LoginErrorRejected marks a login the provider refused. LoginErrorRejected LoginError = "rejected" // LoginErrorExpired marks a missing, stale or mismatched login state. LoginErrorExpired LoginError = "expired" LoginErrorUnavailable LoginError = "unavailable" // LoginErrorFailed marks any other login failure. LoginErrorFailed LoginError = "failed" // LoginQueryParam is the query parameter carrying a LoginError code on the login page. LoginQueryParam = "error" )
func ClassifyLoginError ¶
func ClassifyLoginError(err error) LoginError
ClassifyLoginError maps an error to the LoginError code a handler should redirect with.
type LoginFailure ¶ added in v1.1.0
type LoginFailure struct {
// Code is the stable LoginError code for the login page redirect.
Code LoginError
// Cause is the underlying error, safe to log but not to expose to the browser.
Cause error
}
LoginFailure reports why an OIDC callback failed.
type LoginResult ¶ added in v1.1.0
type LoginResult struct {
// Subject is the verified subject of the id_token.
Subject string
// Redirect is the sanitized, same-origin path requested before the login.
Redirect string
}
LoginResult reports a successful OIDC callback.
type Provider ¶
type Provider struct {
// contains filtered or unexported fields
}
Provider caches OIDC discovery for the current issuer and client ID.
func NewProvider ¶
NewProvider returns a Provider reading its settings through the supplied function.
func (*Provider) Exchange ¶
func (p *Provider) Exchange(ctx context.Context, settings Config, code, verifier, redirectURL string) (string, error)
Exchange redeems the code with PKCE, verifies the id_token and returns its subject.
type SessionManager ¶
type SessionManager interface {
Start(echoContext *echo.Context, subject string, expiresAt time.Time) error
Authenticate(echoContext *echo.Context) (*User, error)
Clear(echoContext *echo.Context) error
CookieName() string
}
SessionManager stores and reads the session behind a request so apps can swap in their own store.