Documentation
¶
Overview ¶
Package authkit is a pragmatic authentication and authorization toolkit for Go web services on PostgreSQL 16+.
Drop authkit into a net/http stack and get registration, password login, opaque server-side sessions, JWT access tokens with rotating refresh, email verification, password reset, magic-link login, email OTP, and owner-agnostic service tokens with consumer-defined abilities. Authorization is flat RBAC with both role-derived and direct user permissions.
Roles, permissions, and abilities are seeded by the consumer (typically via the cmd/perms, cmd/roles, and cmd/abilities CLIs that ship with this repo). The library does not seed any rows automatically — applications own their authorization vocabulary.
Migrations and schema verification run at startup. Set Config.SkipAutoMigrate to disable.
The library does not send email or otherwise reach out to users. Token-minting flows (RequestEmailVerification, RequestPasswordReset, RequestMagicLink, RequestEmailOTP, IssueServiceKey, IssueSession, IssueJWT) return the plaintext to the caller exactly once — show it to the user immediately; only its SHA-256 hash is persisted.
Index ¶
- Constants
- Variables
- func BoolPtr(b bool) *bool
- func HashOpaqueSecret(plaintext string) []byte
- func Migrate(ctx context.Context, db *sql.DB, schema Schema) error
- func MintOpaqueSecret(rng io.Reader, prefix string) (plaintext string, hash []byte, err error)
- func ParseOpaqueSecret(prefix, plaintext string) (hash []byte, ok bool)
- func UserIDFromCtx(ctx context.Context) (uuid.UUID, bool)
- func VerifySchema(ctx context.Context, db *sql.DB, schema Schema) error
- func WithServiceKey(ctx context.Context, k *ServiceKey) context.Context
- func WithUserContext(ctx context.Context, a *Auth, userID uuid.UUID) context.Context
- type Ability
- type Auth
- func (a *Auth) AssignRole(ctx context.Context, userID uuid.UUID, roleSlug string) error
- func (a *Auth) AuthenticateJWT(ctx context.Context, access string) (*Principal, error)
- func (a *Auth) AuthenticateServiceKey(ctx context.Context, plaintext string) (*ServiceKey, error)
- func (a *Auth) AuthenticateSession(ctx context.Context, plaintext string) (*Principal, error)
- func (a *Auth) ChangePassword(ctx context.Context, userID uuid.UUID, oldPassword, newPassword string) error
- func (a *Auth) ClearSessionCookie() *http.Cookie
- func (a *Auth) ConfirmEmail(ctx context.Context, plaintextToken string) (*User, error)
- func (a *Auth) ConfirmPasswordReset(ctx context.Context, plaintextToken, newPassword string) error
- func (a *Auth) ConsumeEmailOTP(ctx context.Context, email, code string) (*User, error)
- func (a *Auth) ConsumeMagicLink(ctx context.Context, plaintextToken string) (*User, error)
- func (a *Auth) CreateAbility(ctx context.Context, slug, label string) (*Ability, error)
- func (a *Auth) CreatePermission(ctx context.Context, slug, label string) (*Permission, error)
- func (a *Auth) CreateRole(ctx context.Context, slug, label string) (*Role, error)
- func (a *Auth) CreateUser(ctx context.Context, email string) (*User, error)
- func (a *Auth) DB() *sql.DB
- func (a *Auth) DeleteAbility(ctx context.Context, slug string) error
- func (a *Auth) DeletePermission(ctx context.Context, slug string) error
- func (a *Auth) DeleteRole(ctx context.Context, slug string) error
- func (a *Auth) DeleteUser(ctx context.Context, userID uuid.UUID) error
- func (a *Auth) GetAbilityBySlug(ctx context.Context, slug string) (*Ability, error)
- func (a *Auth) GetPermissionBySlug(ctx context.Context, slug string) (*Permission, error)
- func (a *Auth) GetRoleBySlug(ctx context.Context, slug string) (*Role, error)
- func (a *Auth) GetUser(ctx context.Context, userID uuid.UUID) (*User, error)
- func (a *Auth) GetUserByEmail(ctx context.Context, email string) (*User, error)
- func (a *Auth) GrantPermissionToRole(ctx context.Context, roleSlug, permSlug string) error
- func (a *Auth) GrantPermissionToUser(ctx context.Context, userID uuid.UUID, permSlug string) error
- func (a *Auth) HasAnyRole(ctx context.Context, userID uuid.UUID, slugs []string) (bool, error)
- func (a *Auth) HasPermission(ctx context.Context, userID uuid.UUID, permSlug string) (bool, error)
- func (a *Auth) HasRole(ctx context.Context, userID uuid.UUID, slug string) (bool, error)
- func (a *Auth) IssueJWT(ctx context.Context, userID uuid.UUID) (access, refresh string, err error)
- func (a *Auth) IssueServiceKey(ctx context.Context, params IssueServiceKeyParams) (string, *ServiceKey, error)
- func (a *Auth) IssueSession(ctx context.Context, userID uuid.UUID, userAgent string, ip netip.Addr) (string, *Session, error)
- func (a *Auth) ListAbilities(ctx context.Context) ([]*Ability, error)
- func (a *Auth) ListPermissions(ctx context.Context) ([]*Permission, error)
- func (a *Auth) ListRolePermissions(ctx context.Context, roleSlug string) ([]*Permission, error)
- func (a *Auth) ListRoles(ctx context.Context) ([]*Role, error)
- func (a *Auth) ListServiceKeys(ctx context.Context) ([]*ServiceKey, error)
- func (a *Auth) LoginPassword(ctx context.Context, email, password string) (*User, error)
- func (a *Auth) RefreshJWT(ctx context.Context, plaintextRefresh string) (access, refresh string, err error)
- func (a *Auth) RemoveRole(ctx context.Context, userID uuid.UUID, roleSlug string) error
- func (a *Auth) RequestEmailOTP(ctx context.Context, email string) (string, error)
- func (a *Auth) RequestEmailVerification(ctx context.Context, userID uuid.UUID) (string, error)
- func (a *Auth) RequestMagicLink(ctx context.Context, email string) (string, error)
- func (a *Auth) RequestPasswordReset(ctx context.Context, email string) (string, error)
- func (a *Auth) RevokeAllUserSessions(ctx context.Context, userID uuid.UUID) error
- func (a *Auth) RevokePermissionFromRole(ctx context.Context, roleSlug, permSlug string) error
- func (a *Auth) RevokePermissionFromUser(ctx context.Context, userID uuid.UUID, permSlug string) error
- func (a *Auth) RevokeServiceKey(ctx context.Context, plaintext string) error
- func (a *Auth) RevokeSession(ctx context.Context, plaintext string) error
- func (a *Auth) Schema() Schema
- func (a *Auth) SessionCookie(plaintext string, expires time.Time) *http.Cookie
- func (a *Auth) SessionCookieName() string
- func (a *Auth) SetPassword(ctx context.Context, userID uuid.UUID, password string) error
- func (a *Auth) UserPermissions(ctx context.Context, userID uuid.UUID) ([]string, error)
- func (a *Auth) UserRoles(ctx context.Context, userID uuid.UUID) ([]string, error)
- type AuthMethod
- type Config
- type Deps
- type Extractor
- type Hasher
- type IssueServiceKeyParams
- type LoginAuthz
- type Permission
- type Principal
- type Role
- type Schema
- type ServiceKey
- type ServiceKeyAuthz
- type Session
- type Tables
- type Token
- type TokenKind
- type User
Constants ¶
const MaxSlugLength = 64
MaxSlugLength is the upper bound on slug length, in bytes. Slugs are ASCII so this also bounds character count.
Variables ¶
var ( ErrEmailTaken = errors.New("authkit: email already registered") ErrUserNotFound = errors.New("authkit: user not found") ErrInvalidCredentials = errors.New("authkit: invalid credentials") ErrTokenInvalid = errors.New("authkit: invalid or expired token") ErrTokenReused = errors.New("authkit: token reuse detected") ErrSessionInvalid = errors.New("authkit: invalid or expired session") ErrServiceKeyInvalid = errors.New("authkit: invalid or expired service key") ErrPermissionDenied = errors.New("authkit: permission denied") ErrRoleNotFound = errors.New("authkit: role not found") ErrPermissionNotFound = errors.New("authkit: permission not found") ErrAbilityNotFound = errors.New("authkit: ability not found") ErrSlugInvalid = errors.New("authkit: invalid slug") ErrSlugTaken = errors.New("authkit: slug already in use") ErrOTPInvalid = errors.New("authkit: invalid or expired OTP") ErrNoUserContext = errors.New("authkit: no user on request context") ErrSchemaDrift = errors.New("authkit: database schema does not match expected layout") )
Sentinel errors. Internal call sites wrap these via errx so callers using errors.Is(err, authkit.ErrFoo) get reliable matching across wrap chains.
Functions ¶
func BoolPtr ¶ added in v0.3.0
BoolPtr is a one-line helper for Config fields that take *bool. Use it to opt out of the secure cookie defaults: cfg.SessionCookieSecure = BoolPtr(false).
func HashOpaqueSecret ¶ added in v0.2.0
HashOpaqueSecret returns sha256(plaintext) — the lookup key for opaque secrets. Plaintexts have full entropy from a CSPRNG so a plain hash is sufficient (no per-record salt needed; the random body is the salt).
func Migrate ¶ added in v0.3.0
Migrate applies every embedded migration not yet recorded in the schema-migrations table. Safe to call repeatedly and concurrently across processes; the advisory lock serialises rollouts. Each migration owns its own BEGIN/COMMIT.
Embedded migrations hard-code the default authkit_* names. If the consumer has overridden any table name, Migrate is a no-op and the consumer is responsible for managing DDL out-of-band.
func MintOpaqueSecret ¶ added in v0.2.0
MintOpaqueSecret generates a fresh opaque secret with the given prefix. Returns the plaintext (show once, never persist) and the SHA-256 lookup hash. A nil rng falls back to crypto/rand.Reader.
func ParseOpaqueSecret ¶ added in v0.2.0
ParseOpaqueSecret validates that a plaintext begins with the expected prefix and returns the lookup hash.
func UserIDFromCtx ¶ added in v0.3.0
UserIDFromCtx returns the authenticated user_id placed by middleware via WithUserContext. The boolean is false when no user-bound auth ran for this request (e.g. a service-key request).
func VerifySchema ¶ added in v0.3.0
VerifySchema introspects the live database against the expected layout for the given schema. Returns a wrapped ErrSchemaDrift describing every missing/mismatched table or column. Extra columns on a table are allowed.
For tables with non-default names, VerifySchema looks up the configured name first; if no rows are found, it falls back to the default name. This handles the case where a consumer migrated under custom names but later removed the overrides — drift is detected against whichever set of names actually exists.
func WithServiceKey ¶ added in v0.3.0
func WithServiceKey(ctx context.Context, k *ServiceKey) context.Context
WithServiceKey attaches a *ServiceKey to ctx. Used by service-key middleware.
func WithUserContext ¶ added in v0.3.0
WithUserContext attaches a lazy user-context to ctx. Middleware uses this to record an authenticated user_id without paying for a DB read until a handler actually calls UserFromCtx. Custom middleware authors can use this directly to integrate hand-rolled auth flows.
Types ¶
type Ability ¶ added in v0.3.0
Ability is a unit of authorization for service tokens. Abilities are a separate vocabulary from Permissions because they target machines, not users — keep them distinct so middleware predicates remain clear about which subject they're authorizing.
type Auth ¶
type Auth struct {
// contains filtered or unexported fields
}
Auth is the high-level service. Safe for concurrent use; method receivers never mutate Auth state after construction.
func New ¶
New validates Deps and Config, fills in defaults, runs migrations (unless SkipAutoMigrate), verifies the schema (unless SkipSchemaVerify), and returns a ready service.
Panics on missing deps, missing JWT secret, invalid schema, or schema drift — these are programmer/operator errors, not runtime failures.
func (*Auth) AssignRole ¶
AssignRole assigns roleSlug to userID. Idempotent — a duplicate insert is a no-op via ON CONFLICT.
func (*Auth) AuthenticateJWT ¶
AuthenticateJWT validates the access JWT, cross-checks the user's session_version (instant revocation), and resolves a Principal.
func (*Auth) AuthenticateServiceKey ¶ added in v0.2.0
AuthenticateServiceKey validates a service token and returns the stored *ServiceKey with its abilities resolved.
func (*Auth) AuthenticateSession ¶
AuthenticateSession validates an opaque session string, slides the TTL, resolves the user's roles+permissions, and returns a Principal.
func (*Auth) ChangePassword ¶
func (a *Auth) ChangePassword(ctx context.Context, userID uuid.UUID, oldPassword, newPassword string) error
ChangePassword verifies the current password, sets the new one, and bumps the user's session_version (invalidating outstanding JWTs). Outstanding opaque sessions are also revoked.
func (*Auth) ClearSessionCookie ¶ added in v0.3.0
ClearSessionCookie returns a cookie that, when set on the response, tells the browser to delete the session cookie. Use on logout.
func (*Auth) ConfirmEmail ¶
ConfirmEmail consumes a verification token and marks the user's email verified. Returns ErrTokenInvalid for missing/expired/already-used tokens.
func (*Auth) ConfirmPasswordReset ¶
ConfirmPasswordReset consumes the reset token, sets the new password, bumps session_version, and revokes outstanding sessions so the reset is a global logout.
func (*Auth) ConsumeEmailOTP ¶ added in v0.3.0
ConsumeEmailOTP verifies a code against the most recent active OTP for the user behind email. Successful match consumes the row. A wrong code decrements attempts_remaining and returns ErrOTPInvalid; reaching zero attempts invalidates the OTP. A successful consume implicitly verifies the email.
func (*Auth) ConsumeMagicLink ¶
ConsumeMagicLink consumes the magic-link token and returns the authenticated user. Callers typically follow with IssueSession or IssueJWT to actually log the user in. A successful consume implicitly verifies the email (the user demonstrably controls the inbox).
func (*Auth) CreateAbility ¶ added in v0.3.0
CreateAbility inserts a new ability for service tokens.
func (*Auth) CreatePermission ¶ added in v0.3.0
CreatePermission inserts a new permission.
func (*Auth) CreateRole ¶ added in v0.3.0
CreateRole inserts a new role. Slug must be a valid normalized slug; returns ErrSlugInvalid otherwise. Returns ErrSlugTaken if the slug is already in use.
func (*Auth) CreateUser ¶ added in v0.3.0
CreateUser registers a new account with the given email. Password is optional — accounts can be created without a credential and have one set later via SetPassword. Returns ErrEmailTaken if the normalized email is already registered.
func (*Auth) DB ¶ added in v0.3.0
DB exposes the underlying *sql.DB. Useful for callers that want to run admin queries on the same pool.
func (*Auth) DeleteAbility ¶ added in v0.3.0
DeleteAbility removes an ability by its slug. Cascades to service_key_abilities.
func (*Auth) DeletePermission ¶ added in v0.3.0
DeletePermission removes a permission by its slug. Cascades to role_permissions and user_permissions.
func (*Auth) DeleteRole ¶ added in v0.3.0
DeleteRole removes a role by its slug. Cascades to user_roles and role_permissions. Returns ErrRoleNotFound if absent.
func (*Auth) DeleteUser ¶ added in v0.3.0
DeleteUser removes the user. Cascades to sessions, tokens, role assignments, and direct permission grants via FK ON DELETE CASCADE.
func (*Auth) GetAbilityBySlug ¶ added in v0.3.0
GetAbilityBySlug fetches an ability by its slug.
func (*Auth) GetPermissionBySlug ¶ added in v0.3.0
GetPermissionBySlug fetches a permission by its slug.
func (*Auth) GetRoleBySlug ¶ added in v0.3.0
GetRoleBySlug fetches a role by its slug.
func (*Auth) GetUser ¶ added in v0.3.0
GetUser fetches the user by ID. Returns ErrUserNotFound if absent.
func (*Auth) GetUserByEmail ¶ added in v0.3.0
GetUserByEmail fetches the user by email (input is normalized internally).
func (*Auth) GrantPermissionToRole ¶ added in v0.3.0
GrantPermissionToRole adds permSlug to roleSlug's permission set. Idempotent.
func (*Auth) GrantPermissionToUser ¶ added in v0.3.0
GrantPermissionToUser adds a direct permission grant (not through any role). Idempotent.
func (*Auth) HasAnyRole ¶
HasAnyRole reports whether the user holds at least one of the named roles.
func (*Auth) HasPermission ¶
HasPermission reports whether the user holds the named permission, via any combination of role-derived and direct grants.
func (*Auth) IssueJWT ¶
IssueJWT issues a fresh access JWT and a rotating opaque refresh token. The refresh token is bound to a chain via Token.ChainID; rotation preserves that chain so reuse-detection can revoke the whole family. chainStartedAt is stamped on this row and copied forward on every rotation so RefreshJWT can enforce RefreshChainAbsoluteTTL in O(1).
func (*Auth) IssueServiceKey ¶ added in v0.2.0
func (a *Auth) IssueServiceKey(ctx context.Context, params IssueServiceKeyParams) (string, *ServiceKey, error)
IssueServiceKey mints a fresh service token. Plaintext is returned exactly once (show-once); only the SHA-256 hash is persisted. Each ability slug is resolved to its row before insertion, so the service key carries a well-defined set of abilities even after later slug renames or deletes.
func (*Auth) IssueSession ¶
func (a *Auth) IssueSession(ctx context.Context, userID uuid.UUID, userAgent string, ip netip.Addr) (string, *Session, error)
IssueSession mints an opaque session ID, persists the session record, and returns the plaintext (for the cookie) plus the stored Session.
func (*Auth) ListAbilities ¶ added in v0.3.0
ListAbilities returns every ability ordered by slug.
func (*Auth) ListPermissions ¶ added in v0.3.0
func (a *Auth) ListPermissions(ctx context.Context) ([]*Permission, error)
ListPermissions returns every permission ordered by slug.
func (*Auth) ListRolePermissions ¶ added in v0.3.0
ListRolePermissions returns permissions granted to a role through the role-permission link only (not direct user grants).
func (*Auth) ListServiceKeys ¶ added in v0.2.0
func (a *Auth) ListServiceKeys(ctx context.Context) ([]*ServiceKey, error)
ListServiceKeys returns every service token, including revoked and expired ones, ordered by creation time descending.
func (*Auth) LoginPassword ¶
LoginPassword verifies the password and returns the authenticated user. Failure does not increment any counter — consumers wanting lockout should implement it via LoginHook (see README). Success resets nothing and stamps last_login_at. LoginHook is invoked with the success outcome.
func (*Auth) RefreshJWT ¶
func (a *Auth) RefreshJWT(ctx context.Context, plaintextRefresh string) (access, refresh string, err error)
RefreshJWT consumes the presented refresh token and mints a new access+refresh pair. Reuse of an already-consumed refresh token deletes the entire chain (logout-everywhere on that device family) and returns ErrTokenReused. The chain itself is capped at RefreshChainAbsoluteTTL from chain_started_at — past that, refresh fails with ErrTokenInvalid and the chain is deleted, forcing the user to re-authenticate.
func (*Auth) RemoveRole ¶
RemoveRole removes roleSlug from userID. Idempotent on missing assignments.
func (*Auth) RequestEmailOTP ¶ added in v0.3.0
RequestEmailOTP mints a numeric one-time code for the email and returns the plaintext for delivery. Anti-enumeration: unknown email returns ("", nil) unless Config.RevealUnknownEmail is set.
Code length is Config.EmailOTPDigits (default 6). Brute-force resistance comes from Config.EmailOTPMaxAttempts (default 5): after N wrong tries the code is invalidated, forcing the caller to request a new one.
func (*Auth) RequestEmailVerification ¶
RequestEmailVerification mints a single-use email-verify token for the user. Return the plaintext to the caller for delivery; the lookup hash is what's stored.
func (*Auth) RequestMagicLink ¶
RequestMagicLink mints a single-use magic-link token for the email and returns the plaintext for delivery.
Default behavior is anti-enumeration: if the email is not registered, returns ("", nil) — the caller cannot distinguish "exists" from "doesn't exist". Set Config.RevealUnknownEmail = true to surface ErrUserNotFound.
func (*Auth) RequestPasswordReset ¶
RequestPasswordReset mints a single-use password-reset token for the user behind email and returns the plaintext for delivery.
Default behavior is anti-enumeration: unknown email returns ("", nil). Set Config.RevealUnknownEmail = true to surface ErrUserNotFound.
func (*Auth) RevokeAllUserSessions ¶
RevokeAllUserSessions kills every active session for the user and bumps session_version (invalidating outstanding JWT access tokens).
func (*Auth) RevokePermissionFromRole ¶ added in v0.3.0
RevokePermissionFromRole removes permSlug from roleSlug's permission set. Idempotent.
func (*Auth) RevokePermissionFromUser ¶ added in v0.3.0
func (a *Auth) RevokePermissionFromUser(ctx context.Context, userID uuid.UUID, permSlug string) error
RevokePermissionFromUser removes a direct permission grant.
func (*Auth) RevokeServiceKey ¶ added in v0.2.0
RevokeServiceKey marks a service token revoked. Idempotent on already-revoked keys.
func (*Auth) RevokeSession ¶
RevokeSession deletes a single session by its plaintext id. Idempotent — missing sessions are not an error.
func (*Auth) SessionCookie ¶
SessionCookie builds an *http.Cookie pre-configured from Config. Pass the plaintext returned by IssueSession and the matching ExpiresAt from the returned *Session.
func (*Auth) SessionCookieName ¶ added in v0.3.0
SessionCookieName returns the configured cookie name. Useful for callers wiring extractors without reaching into Config.
func (*Auth) SetPassword ¶ added in v0.3.0
SetPassword stores a password hash for the user. Use for the initial-credential flow and for administrative password changes. Bumping session_version is the caller's responsibility; SetPassword does not invalidate existing sessions on its own. ChangePassword is the safer wrapper for end-user-driven changes.
func (*Auth) UserPermissions ¶
UserPermissions returns the union of permission slugs the user holds via roles and direct grants.
type AuthMethod ¶
type AuthMethod string
AuthMethod tags how a Principal was authenticated.
const ( AuthMethodSession AuthMethod = "session" AuthMethodJWT AuthMethod = "jwt" )
type Config ¶
type Config struct {
// Schema lets consumers override table names. Zero value uses
// DefaultSchema().
Schema Schema
// SkipAutoMigrate disables the migration run inside New. The verifier
// still runs; consumers running their own migrate pipeline should set
// this and call authkit.Migrate manually before New (or skip it
// entirely if they manage DDL out-of-band).
SkipAutoMigrate bool
// SkipSchemaVerify disables the startup schema check. Recommended only
// for tests that expect schema drift; production callers should let the
// verifier run.
SkipSchemaVerify bool
// Sessions
SessionIdleTTL time.Duration
SessionAbsoluteTTL time.Duration
SessionCookieName string
SessionCookieDomain string
SessionCookiePath string
// SessionCookieSecure / SessionCookieHTTPOnly use *bool so a nil value
// means "fall back to the secure default (true)" while *bool(false) is
// an explicit opt-out for local dev. BoolPtr is a one-line constructor.
SessionCookieSecure *bool
SessionCookieHTTPOnly *bool
SessionCookieSameSite http.SameSite
// JWT (HS256)
JWTSecret []byte
JWTIssuer string
JWTAudience string
AccessTokenTTL time.Duration
RefreshTokenTTL time.Duration
// RefreshChainAbsoluteTTL caps the maximum lifetime of a refresh chain.
// A user can refresh as often as they want within RefreshTokenTTL of the
// last rotation, but the chain itself dies once now > chainStartedAt +
// RefreshChainAbsoluteTTL — at which point the user must re-authenticate.
// Mirrors SessionAbsoluteTTL on the session path.
RefreshChainAbsoluteTTL time.Duration
// Single-use tokens
EmailVerifyTTL time.Duration
PasswordResetTTL time.Duration
MagicLinkTTL time.Duration
EmailOTPTTL time.Duration
EmailOTPMaxAttempts int
EmailOTPDigits int
// RevealUnknownEmail flips request flows (RequestPasswordReset,
// RequestMagicLink, RequestEmailOTP) from anti-enumeration silent
// success to returning ErrUserNotFound when the email isn't
// registered. Default false (silent).
RevealUnknownEmail bool
// Hooks
Clock func() time.Time
Random io.Reader
LoginHook func(ctx context.Context, email string, success bool) error
}
Config tunes session/JWT/token TTLs, cookie shape, JWT signing material, schema overrides, and optional hooks. Zero-valued durations are replaced with sane defaults in New; required fields (notably JWTSecret) cause New to panic.
type Deps ¶
Deps bundles the runtime dependencies the Auth service requires. DB and Hasher are required; New panics on either being nil.
type Extractor ¶
Extractor pulls a credential string out of an HTTP request. Returns (value, true) when found, ("", false) otherwise.
func BearerExtractor ¶
func BearerExtractor() Extractor
BearerExtractor reads the value following "Bearer " in the Authorization header. Comparison is case-insensitive on the scheme.
func ChainExtractors ¶
ChainExtractors tries each extractor in order, returning the first hit.
func CookieExtractor ¶
CookieExtractor reads the named cookie's value.
func HeaderExtractor ¶
HeaderExtractor reads a custom header verbatim.
type Hasher ¶
type Hasher interface {
Hash(password string) (string, error)
Verify(password, encoded string) (ok bool, needsRehash bool, err error)
}
Hasher is the password hashing interface. The default implementation is hasher.Argon2id; consumers can swap in alternative KDFs as long as the encoded form lets Verify roundtrip and report needsRehash on parameter drift.
type IssueServiceKeyParams ¶ added in v0.3.0
IssueServiceKeyParams is the input shape for IssueServiceKey. Abilities are slugs that must already exist in authkit_abilities — issue fails with ErrAbilityNotFound if any slug is unknown. TTL is optional; nil means non-expiring.
type LoginAuthz ¶ added in v0.3.0
type LoginAuthz interface {
// Match reports whether the principal satisfies the predicate.
Match(p *Principal) bool
// Validate verifies that every slug referenced by this predicate exists
// in the database. Called at middleware-construction time so typos fail
// at boot rather than at request time.
Validate(ctx context.Context, a *Auth) error
}
LoginAuthz is a predicate over a *Principal. Used by middleware that gates handlers on a user's roles or permissions.
func AllLogin ¶ added in v0.3.0
func AllLogin(preds ...LoginAuthz) LoginAuthz
AllLogin returns a predicate satisfied when every child predicate matches. With no children, AllLogin matches everything (returns true).
func AnyLogin ¶ added in v0.3.0
func AnyLogin(preds ...LoginAuthz) LoginAuthz
AnyLogin returns a predicate satisfied when at least one child predicate matches. With no children, AnyLogin matches nothing (returns false).
func HasPermission ¶ added in v0.3.0
func HasPermission(slug string) LoginAuthz
HasPermission returns a leaf predicate satisfied when the principal carries the given permission slug (resolved through any combination of roles and direct grants).
func HasRole ¶ added in v0.3.0
func HasRole(slug string) LoginAuthz
HasRole returns a leaf predicate satisfied when the principal carries the given role slug.
type Permission ¶
Permission is a unit of authorization. Granted to users either through a role or directly via authkit_user_permissions.
type Principal ¶
type Principal struct {
UserID uuid.UUID
Method AuthMethod
SessionID []byte
Roles []string
Permissions []string
IssuedAt time.Time
ExpiresAt time.Time
}
Principal represents an authenticated user. Produced only by user-bound auth methods (session, JWT) and carries identity plus RBAC-resolved roles and permissions. Service-token auth produces a *ServiceKey instead — those credentials carry abilities, not identity.
func (*Principal) HasAnyRole ¶
HasAnyRole reports whether the principal holds at least one of the named role slugs.
func (*Principal) HasPermission ¶
HasPermission reports whether the principal holds the named permission slug, resolved through any combination of roles and direct grants.
type Role ¶
Role groups permissions for assignment to users. Slug is the immutable business key; Label is an optional human-readable name.
type Schema ¶ added in v0.3.0
type Schema struct {
Tables Tables
}
Schema lets consumers map authkit storage to their own table names. Column overrides are not exposed in v1 — the column set is fixed.
func DefaultSchema ¶ added in v0.3.0
func DefaultSchema() Schema
DefaultSchema returns the stock authkit_* names matching the embedded migration files.
type ServiceKey ¶ added in v0.2.0
type ServiceKey struct {
IDHash []byte
Name string
Abilities []string
LastUsedAt *time.Time
CreatedAt time.Time
ExpiresAt *time.Time
RevokedAt *time.Time
}
ServiceKey is a machine credential. It carries no identity — service tokens are produced by applications for outbound API access or inbound automation, and authorize via Abilities resolved through the join table.
func ServiceKeyFromCtx ¶ added in v0.3.0
func ServiceKeyFromCtx(ctx context.Context) (*ServiceKey, bool)
ServiceKeyFromCtx returns the authenticated *ServiceKey placed by service-key middleware. The boolean is false when no service-key authentication ran for this request.
func (*ServiceKey) HasAbility ¶ added in v0.2.0
func (k *ServiceKey) HasAbility(slug string) bool
HasAbility reports whether the service key carries the named ability slug.
type ServiceKeyAuthz ¶ added in v0.3.0
type ServiceKeyAuthz interface {
Match(k *ServiceKey) bool
Validate(ctx context.Context, a *Auth) error
}
ServiceKeyAuthz is the analogous predicate type for service-token authorization.
func AllServiceKey ¶ added in v0.3.0
func AllServiceKey(preds ...ServiceKeyAuthz) ServiceKeyAuthz
AllServiceKey returns a service-key predicate satisfied when every child matches.
func AnyServiceKey ¶ added in v0.3.0
func AnyServiceKey(preds ...ServiceKeyAuthz) ServiceKeyAuthz
AnyServiceKey returns a service-key predicate satisfied when at least one child matches.
func HasAbility ¶ added in v0.3.0
func HasAbility(slug string) ServiceKeyAuthz
HasAbility returns a leaf predicate satisfied when the service key carries the given ability slug.
type Session ¶
type Session struct {
IDHash []byte
UserID uuid.UUID
UserAgent string
IP netip.Addr
CreatedAt time.Time
LastSeenAt time.Time
ExpiresAt time.Time
}
Session is an opaque server-side credential bound to one user.
type Tables ¶ added in v0.3.0
type Tables struct {
Users string
Sessions string
Tokens string
ServiceKeys string
ServiceKeyAbilities string
Roles string
Permissions string
Abilities string
UserRoles string
UserPermissions string
RolePermissions string
SchemaMigrations string
}
Tables holds per-table identifier overrides. Every field must be a valid unquoted SQL identifier (matching identifierRE). Validation runs at New()/Migrate() time so SQL injection through Schema is impossible past that gate.
type Token ¶
type Token struct {
Hash []byte
Kind TokenKind
UserID uuid.UUID
ChainID *string
ChainStartedAt *time.Time
ConsumedAt *time.Time
AttemptsRemaining *int
CreatedAt time.Time
ExpiresAt time.Time
}
Token is one row in authkit_tokens. AttemptsRemaining is non-nil only for tokens that allow retry on incorrect input (email OTPs); other kinds are strictly one-shot via ConsumeToken. ChainStartedAt is non-nil only for refresh-token rows; copied forward on every rotation so the absolute-cap check in RefreshJWT is O(1).
type TokenKind ¶
type TokenKind string
TokenKind enumerates the single-use credentials persisted in authkit_tokens.
type User ¶
type User struct {
ID uuid.UUID
Email string
EmailNormalized string
EmailVerifiedAt *time.Time
PasswordHash string
SessionVersion int
LastLoginAt *time.Time
CreatedAt time.Time
UpdatedAt time.Time
}
User is the canonical account record. Password hash is empty (and stored NULL in the DB) when no credential has been set — accounts created via invite or magic-link-only flows live in this state until SetPassword runs.
func RefreshUserInCtx ¶ added in v0.3.0
RefreshUserInCtx invalidates the cached user and refetches. Use after an admin-side update that should be visible to the rest of the request.
Source Files
¶
- authkit.go
- authz.go
- doc.go
- email.go
- errors.go
- extractor.go
- jwt.go
- models.go
- principal.go
- service_authz.go
- service_jwt.go
- service_magic.go
- service_otp.go
- service_reset.go
- service_seed.go
- service_service_key.go
- service_session.go
- service_user.go
- slug.go
- store_abilities.go
- store_errors.go
- store_migrate.go
- store_permissions.go
- store_queries.go
- store_roles.go
- store_scan.go
- store_schema.go
- store_service_keys.go
- store_sessions.go
- store_tokens.go
- store_users.go
- store_verify.go
- tokens.go
- userctx.go
Directories
¶
| Path | Synopsis |
|---|---|
|
cmd
|
|
|
abilities
command
Command abilities is the seeding CLI for service-token abilities.
|
Command abilities is the seeding CLI for service-token abilities. |
|
internal/clihelp
Package clihelp is a small helper used by the cmd/perms, cmd/roles, and cmd/abilities seeding CLIs to dial Postgres, build an *authkit.Auth, and share argument-parsing scaffolding.
|
Package clihelp is a small helper used by the cmd/perms, cmd/roles, and cmd/abilities seeding CLIs to dial Postgres, build an *authkit.Auth, and share argument-parsing scaffolding. |
|
perms
command
Command perms is the seeding CLI for authkit permissions.
|
Command perms is the seeding CLI for authkit permissions. |
|
roles
command
Command roles is the seeding CLI for authkit roles, plus role↔permission linking.
|
Command roles is the seeding CLI for authkit roles, plus role↔permission linking. |
|
Package hasher provides password-hashing primitives that satisfy the authkit.Hasher interface.
|
Package hasher provides password-hashing primitives that satisfy the authkit.Hasher interface. |
|
Package middleware provides framework-neutral HTTP middleware for authkit.
|
Package middleware provides framework-neutral HTTP middleware for authkit. |