Documentation
¶
Overview ¶
Package auth authenticates requests: guards (session for browsers, access tokens for APIs), user providers, middleware and password hashing (auth/hash). See docs/authentication.md.
Index ¶
- Constants
- Variables
- func Ability(guard Checker, abilities ...string) func(http.Handler) http.Handler
- func Guest(guards ...Checker) func(http.Handler) http.Handler
- func Optional(guards ...Checker) func(http.Handler) http.Handler
- func Required(guards ...Checker) func(http.Handler) http.Handler
- func TokenCan(c *web.Ctx, guard, ability string) bool
- func User[U Authenticatable](c *web.Ctx, guard string) (U, error)
- func UserFrom[U any](ctx context.Context, guard string) (U, error)
- func Verified(guard Checker) func(http.Handler) http.Handler
- type Authenticatable
- type Checker
- type LoginOption
- type ORMProvider
- type PasswordUpdater
- type RememberStore
- type SessionGuard
- func (g *SessionGuard[U]) Attempt(c *web.Ctx, creds map[string]string, opts ...LoginOption) (U, error)
- func (g *SessionGuard[U]) Check(c *web.Ctx) bool
- func (g *SessionGuard[U]) Login(c *web.Ctx, u U, opts ...LoginOption) error
- func (g *SessionGuard[U]) Logout(c *web.Ctx) error
- func (g *SessionGuard[U]) Name() string
- func (g *SessionGuard[U]) User(c *web.Ctx) (U, error)
- func (g *SessionGuard[U]) Validate(c *web.Ctx, creds map[string]string) (U, error)
- type Token
- type TokenGuard
- type Tokens
- func (t *Tokens) Create(ctx context.Context, userID, name string, abilities []string, ...) (string, Token, error)
- func (t *Tokens) Find(ctx context.Context, plain string) (Token, error)
- func (t *Tokens) Revoke(ctx context.Context, id string) error
- func (t *Tokens) RevokeAll(ctx context.Context, userID string) error
- type UserProvider
- type Verifiable
Constants ¶
const IntendedKey = "url.intended"
IntendedKey is the session key holding the URL a guest tried to open; login handlers redirect there (web.SafeRedirect) after success.
Variables ¶
var ( // ErrUnauthenticated is 401 (WWW-Authenticate is added by middleware). ErrUnauthenticated = &errs.HTTPError{Status: http.StatusUnauthorized, Message: "Unauthenticated."} // ErrUserNotFound is returned by providers for unknown users. ErrUserNotFound = errors.New("auth: user not found") )
Errors returned by guards.
Functions ¶
func Ability ¶
Ability requires the request's access token (from guard) to grant every ability; 403 otherwise. Place it after Required.
func Guest ¶
Guest sends authenticated users to the route named "home" (or "/"); use it on login and register pages.
func Optional ¶ added in v0.14.0
Optional authenticates the request when a guard can (so handlers, policies and templates see the user) and never blocks it.
func Required ¶
Required lets the request through when any guard authenticates it. JSON and API clients get 401 (with WWW-Authenticate: Bearer when a token guard is involved); browsers are redirected to the route named "login", and the intended URL is remembered for GET requests.
func User ¶
func User[U Authenticatable](c *web.Ctx, guard string) (U, error)
User returns the user authenticated by guard for this request (after Required or a guard's Check ran).
Types ¶
type Authenticatable ¶
type Authenticatable interface {
// AuthID is the user's primary key as a string.
AuthID() string
// AuthPassword is the stored password hash.
AuthPassword() string
}
Authenticatable is a user model.
type Checker ¶
type Checker interface {
// Name identifies the guard ("web", "api").
Name() string
// Check reports whether c is authenticated, caching the user in c.
Check(c *web.Ctx) bool
}
Checker is the non-generic part of a guard, used by middleware.
type ORMProvider ¶
type ORMProvider[U Authenticatable] struct { PasswordColumn string // contains filtered or unexported fields }
ORMProvider loads users of model U with the ORM: ByID by primary key, ByCredentials by every credential except "password" (column names are validated against U). Its PasswordColumn (default "password") receives rehashed passwords.
func NewORMProvider ¶
func NewORMProvider[U Authenticatable](ex database.Executor) *ORMProvider[U]
NewORMProvider returns the default provider for model U.
func (*ORMProvider[U]) ByCredentials ¶
ByCredentials implements UserProvider.
func (*ORMProvider[U]) ByID ¶
func (p *ORMProvider[U]) ByID(ctx context.Context, id string) (U, error)
ByID implements UserProvider.
func (*ORMProvider[U]) UpdatePassword ¶
func (p *ORMProvider[U]) UpdatePassword(ctx context.Context, u U, hash string) error
UpdatePassword implements PasswordUpdater.
type PasswordUpdater ¶
type PasswordUpdater[U Authenticatable] interface { UpdatePassword(ctx context.Context, u U, hash string) error }
PasswordUpdater is implemented by providers that can store a rehashed password after login (hash.Hasher.NeedsRehash).
type RememberStore ¶
type RememberStore struct {
// contains filtered or unexported fields
}
RememberStore keeps remember-me tokens: the cookie holds "<id>.<secret>" and only SHA-256(secret) is stored. Table (created by install:auth): remember_tokens(id TEXT PRIMARY KEY, user_id TEXT, hash TEXT, expires_at TIMESTAMP).
func NewRememberStore ¶
func NewRememberStore(ex database.Executor) *RememberStore
NewRememberStore uses the remember_tokens table.
type SessionGuard ¶
type SessionGuard[U Authenticatable] struct { // IdentifierField is where failed-login errors are reported ("email"). IdentifierField string // RememberFor is the remember-me cookie lifetime (default 30 days). RememberFor time.Duration // InsecureCookies drops the Secure flag on the remember-me cookie // (plain-HTTP development without localhost only). InsecureCookies bool // contains filtered or unexported fields }
SessionGuard authenticates browsers with the session: the user id is stored under "auth_<name>" after login.
func NewSessionGuard ¶
func NewSessionGuard[U Authenticatable](name string, p UserProvider[U], h hash.Hasher, remember *RememberStore, ) *SessionGuard[U]
NewSessionGuard returns the "web" style guard. remember may be nil to disable remember-me.
func (*SessionGuard[U]) Attempt ¶
func (g *SessionGuard[U]) Attempt(c *web.Ctx, creds map[string]string, opts ...LoginOption) (U, error)
Attempt checks creds (identifier columns + "password") and logs the user in. It returns a 422 validation error on the identifier field when they do not match, taking the same time whether or not the user exists.
func (*SessionGuard[U]) Check ¶
func (g *SessionGuard[U]) Check(c *web.Ctx) bool
Check implements Checker: session user, else a valid remember-me cookie.
func (*SessionGuard[U]) Login ¶
func (g *SessionGuard[U]) Login(c *web.Ctx, u U, opts ...LoginOption) error
Login logs u in: the session id is regenerated (fixation) and the user id stored.
func (*SessionGuard[U]) Logout ¶
func (g *SessionGuard[U]) Logout(c *web.Ctx) error
Logout clears the session (new id, no data) and the remember-me token.
func (*SessionGuard[U]) User ¶
func (g *SessionGuard[U]) User(c *web.Ctx) (U, error)
User returns the logged-in user (cached for the request) or ErrUnauthenticated.
type Token ¶
type Token struct {
ID string `json:"id"`
UserID string `json:"user_id"`
Name string `json:"name"`
Abilities []string `json:"abilities"`
LastUsedAt *time.Time `json:"last_used_at"`
ExpiresAt *time.Time `json:"expires_at"`
}
Token describes an access token (never the secret).
func CurrentToken ¶
CurrentToken returns the token that authenticated c with guard.
type TokenGuard ¶
type TokenGuard[U Authenticatable] struct { // contains filtered or unexported fields }
TokenGuard authenticates "Authorization: Bearer <token>" requests.
func NewTokenGuard ¶
func NewTokenGuard[U Authenticatable](name string, p UserProvider[U], tokens *Tokens) *TokenGuard[U]
NewTokenGuard returns the "api" style guard.
type Tokens ¶
type Tokens struct {
// contains filtered or unexported fields
}
Tokens issues and checks opaque access tokens "<id>.<secret>"; only SHA-256(secret) is stored. Table (created by install:auth / install:api): access_tokens(id TEXT PRIMARY KEY, user_id TEXT, name TEXT, hash TEXT, abilities TEXT, last_used_at TIMESTAMP NULL, expires_at TIMESTAMP NULL, created_at TIMESTAMP).
func (*Tokens) Create ¶
func (t *Tokens) Create( ctx context.Context, userID, name string, abilities []string, ttl time.Duration, ) (string, Token, error)
Create issues a token for userID and returns the plain value, shown to the client once. ttl 0 means no expiry.
func (*Tokens) Find ¶
Find validates a plain token and returns it, or errBadToken. It updates last_used_at at most once a minute.
type UserProvider ¶
type UserProvider[U Authenticatable] interface { ByID(ctx context.Context, id string) (U, error) ByCredentials(ctx context.Context, creds map[string]string) (U, error) }
UserProvider loads users. ByCredentials never checks the password; the guard does, in constant time.
type Verifiable ¶
type Verifiable interface {
EmailVerified() bool
}
Verifiable is a user whose email address can be verified.