authall

package module
v0.4.1 Latest Latest
Warning

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

Go to latest
Published: Sep 11, 2026 License: MIT Imports: 35 Imported by: 0

README

Auth-All

Auth-All is an authentication framework that runs inside a Go application.

It provides the capabilities a developer normally assembles from several libraries: users, accounts, database-backed sessions, email and password authentication, email verification, password reset, TOTP two-factor authentication, magic links, OAuth and OpenID Connect, account linking, roles, API keys, user administration, rate limits, audit events, plugins, schema tooling, an OpenAPI contract, and a generated TypeScript client.

Auth-All is not an identity server. The application keeps its database, its HTTP server, and its user interface.

Install

Auth-All needs Go 1.25 or newer.

go get github.com/alternayte/auth-all

Auth-All pulls no database driver that the application does not use. An application that imports store/postgres gets pgx and no SQLite, and the reverse holds too.

The TypeScript client is a separate npm package:

npm install @alternayte/auth-all-client

The operator tool is available as a prebuilt binary on the releases page. A Go user can also install it directly:

go install github.com/alternayte/auth-all/cmd/auth-all@latest

Use

auth, err := authall.New(
    authall.WithStore(postgres.New(db)),
    authall.WithBaseURL("https://app.example.com"),
    authall.WithEmailPassword(),
    authall.WithEmailSender(sender),
    authall.WithProvider(
        github.New(
            github.WithClientID(clientID),
            github.WithClientSecret(clientSecret),
        ),
    ),
    authall.WithPlugins(
        magiclink.New(),
    ),
)
if err != nil {
    log.Fatal(err)
}

mux.Handle("/api/auth/", auth.Handler())

Authorization, machine access, and administration are opt-in plugins:

r := roles.New(roles.Hierarchy("viewer", "operator", "editor", "admin"))
adm := admin.New(admin.AdminRole("admin"))

auth, err := authall.New(
    authall.WithStore(postgres.New(db)),
    authall.WithBaseURL("https://app.example.com"),
    authall.WithEmailPassword(),
    authall.WithPlugins(r, adm, apikeys.New()),
)

// A route asks for a minimum role. A session and an API key both pass it.
mux.Handle("/deploy", r.Require("operator", deployHandler))

// The first administrator comes from the application, and never from a start.
created, err := adm.Bootstrap(ctx, admin.Credentials{Email: e, Password: p})

Create the tables one time before the first start:

go run github.com/alternayte/auth-all/cmd/auth-all migrate \
    --driver postgres --dsn "$DATABASE_URL"

Properties

  • net/http native and framework agnostic. It also serves under a router that removes the base path, and it merges into a huma OpenAPI document.
  • The application owns the database. PostgreSQL and SQLite are supported. The PostgreSQL store runs over a database/sql handle or over a pgxpool.Pool, and it is safe behind a transaction pooler.
  • Secure defaults. Opaque session tokens, hashed tokens at rest, Argon2id password hashing, OAuth state validation, PKCE where the provider supports it, and conservative account linking.
  • TOTP two-factor authentication with recovery codes. One code authenticates one time. The gate covers the password, the magic link, and the OAuth callback.
  • Authorization through an ordered role hierarchy. A route asks for a minimum role. A role that the configuration does not name ranks below every role.
  • Organizations with fine-grained permissions. A person belongs to many organizations, a membership carries a role, and a route asks for a permission of the form resource:action. The check runs in the process and needs no round trip.
  • Machine access through API keys. One key carries 32 random bytes, the store keeps the digest, and the current owner role always caps the key role.
  • User administration with a temporary password, a disable that revokes every session, and a guard that keeps one enabled administrator.
  • A rate limiter that counts in the database, so every instance shares one count. A refused request answers 429 with Retry-After.
  • Audit events that name the actor, the target, the client address, and the authentication method. No event carries a secret.
  • Cross-site protection for the application routes of a cookie request.
  • Plugins are first class. Every official plugin uses the same public plugin API that a third-party plugin uses.
  • One OpenAPI contract produces the official TypeScript client.

What the application controls

  • The table prefix, uuid primary keys, and host-owned columns on the users table.
  • The migration files. Auth-All exports ordered units for goose or for any other tool, and it never runs a migration on its own.
  • The public error envelope, the cookie attributes, and the Argon2id cost.
  • The consistency bound. With no cache every request reads the store, so a disable, a role change, and a key revocation take effect at once.

Documentation

Guide Content
Getting started The first integration, step by step.
Email and password Sign-up, sign-in, verification, and reset.
Sessions Session storage, cookies, and revocation.
Two-factor authentication TOTP enrolment and sign-in.
Magic Link The official sign-in link plugin.
GitHub OAuth GitHub sign-in.
Any OpenID Connect provider Keycloak, Auth0, Okta, Entra ID, and any conformant issuer.
Google OAuth Google sign-in.
Account management Password change, address change, and account delete.
Account linking The linking policy and its threats.
Roles The role hierarchy and the route checks.
API keys Machine credentials and their limits.
Organizations Organizations, members, and the active organization.
Permissions The statements, the roles, the custom roles, and the teams.
Invitations The invitation token, the acceptance, and the message.
External policy The per-object boundary and the ObjectChecker seam.
User administration The administrative routes and the operator methods.
Bootstrap The first administrator and the CLI user commands.
Rate limits The rules and the store-backed limiter.
PostgreSQL The PostgreSQL adapter.
SQLite The SQLite adapter.
Migrations and the CLI Schema operations.
Host-owned migrations The exported units, the table prefix, and the user fields.
huma The adapter for a huma OpenAPI application.
Plugin authors The public extension surface.
TypeScript client The generated client.
Deployment Cookies, origins, proxies, and a troubleshooting table.
Security model Threat assumptions and defenses.

Two official examples show a complete integration:

Development

The repository exposes one command:

just verify

It formats, analyses, tests, starts the PostgreSQL test container, runs the race detector, checks the generated artifacts, tests the TypeScript client, builds the examples, and writes artifacts/verification.md.

License

MIT. See LICENSE.

Documentation

Overview

Package authall is an embedded authentication framework for Go applications.

Auth-All runs inside the application, stores its data in the database the application owns, and integrates through net/http.

Index

Constants

View Source
const (
	DefaultBasePath   = "/api/auth"
	DefaultCookieName = "authall.session"
	// DefaultSessionTTL is the absolute lifetime of a session. A session ends
	// at this age, even when the person stays active.
	DefaultSessionTTL = 30 * 24 * time.Hour
	// DefaultSessionIdleTimeout ends a session that saw no request for this
	// long.
	DefaultSessionIdleTimeout = 7 * 24 * time.Hour
	// DefaultSessionTouchInterval limits how often a session read writes
	// last_seen_at.
	DefaultSessionTouchInterval = 5 * time.Minute
	DefaultVerificationTTL      = 24 * time.Hour
	DefaultPasswordResetTTL     = time.Hour
	DefaultOAuthStateTTL        = 15 * time.Minute
)

Defaults used when an option is not supplied.

View Source
const (
	// MethodSession names a request that a session token authenticated.
	MethodSession = "session"
	// MethodAPIKey names a request that an API key authenticated.
	MethodAPIKey = "api_key"
)

Authentication methods of a principal.

View Source
const DefaultConsistencyBound = 5 * time.Second

DefaultConsistencyBound is the maximum time between a committed change and its effect on every instance.

With no cache, every request reads the credential and the user from the store, so the effective bound is zero.

View Source
const MFATokenKind = "mfa"

MFATokenKind names the one-time token of a pending second factor.

View Source
const RecoveryCodeCount = 10

RecoveryCodeCount is the number of recovery codes of one enrolment.

View Source
const Version = "1.0.0"

Version is the Auth-All API contract version.

Variables

View Source
var (
	ErrInvalidRequest     = apierr.ErrInvalidRequest
	ErrInvalidCredentials = apierr.ErrInvalidCredentials
	ErrEmailAlreadyExists = apierr.ErrEmailAlreadyExists
	ErrWeakPassword       = apierr.ErrWeakPassword
	ErrInvalidToken       = apierr.ErrInvalidToken
	ErrUnauthorized       = apierr.ErrUnauthorized
	ErrForbidden          = apierr.ErrForbidden
	ErrNotFound           = apierr.ErrNotFound
	ErrLastAuthMethod     = apierr.ErrLastAuthMethod
	// ErrNoPasswordCredential reports that the account has no password. An
	// OAuth-only user reaches it.
	ErrNoPasswordCredential = apierr.ErrNoPasswordCredential

	// Re-exported errors of the v0.3.0 release.
	ErrInsufficientRole       = apierr.ErrInsufficientRole
	ErrRoleUnknown            = apierr.ErrRoleUnknown
	ErrRoleNotAllowed         = apierr.ErrRoleNotAllowed
	ErrUserDisabled           = apierr.ErrUserDisabled
	ErrPasswordChangeRequired = apierr.ErrPasswordChangeRequired
	ErrLastAdmin              = apierr.ErrLastAdmin
	ErrAPIKeyExpiryTooLong    = apierr.ErrAPIKeyExpiryTooLong
	ErrAPIKeyExpiryRequired   = apierr.ErrAPIKeyExpiryRequired
)

Re-exported public errors.

Functions

func Field added in v0.3.0

func Field[T any](user *store.User, name string) (T, error)

Field returns the value of one host-owned user field.

It reports an error when the field is absent, and when the stored value has another type than T.

team, err := authall.Field[string](user, "team")

func SessionFrom added in v0.2.0

func SessionFrom(ctx context.Context) *store.Session

SessionFrom returns the session that RequireAuth or LoadSession attached to the request context. It returns nil for any other context.

func UserFrom added in v0.2.0

func UserFrom(ctx context.Context) *store.User

UserFrom returns the user that RequireAuth or LoadSession attached to the request context. It returns nil for any other context.

Types

type AccountLinkingOptions

type AccountLinkingOptions struct {
	// AllowVerifiedEmailAutoLink links an external account to an existing user
	// when the provider proves the same verified email address. It is off by
	// default, because email matching alone allows account takeover through a
	// provider that does not verify addresses.
	AllowVerifiedEmailAutoLink bool
}

AccountLinkingOptions configures how an external account joins a user.

type Argon2Params

type Argon2Params = crypto.Argon2Params

Argon2Params re-exports the password hashing parameters.

func DefaultArgon2Params

func DefaultArgon2Params() Argon2Params

DefaultArgon2Params returns the default password hashing cost.

type Auth

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

Auth is a configured Auth-All instance.

func New

func New(opts ...Option) (*Auth, error)

New builds an Auth-All instance from functional options.

func (*Auth) Accounts

func (a *Auth) Accounts(ctx context.Context, userID string) ([]store.Account, error)

Accounts returns the external accounts of one user.

func (*Auth) BasePath

func (a *Auth) BasePath() string

BasePath returns the configured base path.

func (*Auth) ChangePassword added in v0.4.0

func (a *Auth) ChangePassword(ctx context.Context, in ChangePasswordInput) error

ChangePassword replaces the password of the owner of the account.

The change needs the current password. It revokes every other session of the user, and it clears the temporary password state in the same transaction.

func (*Auth) CheckSchema

func (a *Auth) CheckSchema(ctx context.Context) error

CheckSchema reports an actionable error when the database schema is missing or outdated. Auth-All never migrates a schema on its own.

The default mode reads the Auth-All record table. SchemaCheckCatalog reads the database catalog, which fits a host that applies the exported migrations with its own tool.

func (*Auth) Cleanup

func (a *Auth) Cleanup(ctx context.Context) error

Cleanup removes expired sessions, tokens, and OAuth states.

func (*Auth) ClearSessionCookie added in v0.4.0

func (a *Auth) ClearSessionCookie(w http.ResponseWriter)

ClearSessionCookie removes the session cookie. A host calls it after a sign-out.

func (*Auth) ConsistencyBound added in v0.3.0

func (a *Auth) ConsistencyBound() time.Duration

ConsistencyBound returns the configured bound.

func (*Auth) CreateUser

func (a *Auth) CreateUser(ctx context.Context, in CreateUserInput) (*store.User, error)

CreateUser creates a user, and a password credential when a password is supplied. It returns apierr.ErrEmailAlreadyExists for a duplicate address.

func (*Auth) DefaultRole added in v0.3.0

func (a *Auth) DefaultRole() string

DefaultRole returns the role of a user whose role column is empty.

func (*Auth) ExportMigrations added in v0.3.0

func (a *Auth) ExportMigrations(d schema.Dialect, f migrations.Format) ([]migrations.File, error)

ExportMigrations returns the migration files of the enabled units, sorted by version. The host applies them with its own migration tool.

func (*Auth) GetUser

func (a *Auth) GetUser(ctx context.Context, id string) (*store.User, error)

GetUser returns one user by id.

func (*Auth) GetUserByEmail

func (a *Auth) GetUserByEmail(ctx context.Context, address string) (*store.User, error)

GetUserByEmail returns one user by the normalized form of an address.

func (*Auth) Handler

func (a *Auth) Handler() http.Handler

Handler returns the Auth-All HTTP handler. Mount it at the configured base path, for example mux.Handle("/api/auth/", auth.Handler()).

func (*Auth) HandlerStripped added in v0.3.0

func (a *Auth) HandlerStripped() http.Handler

HandlerStripped returns the Auth-All handler for a router that already removed the base path.

mux.Handle("/api/auth/", http.StripPrefix("/api/auth", auth.HandlerStripped()))

Handler removes the base path itself, so a router that also removes it would leave no path for the route table.

func (*Auth) Hooks

func (a *Auth) Hooks() *hook.Hooks

Hooks returns the lifecycle hook registry of the instance.

func (*Auth) LoadSession added in v0.2.0

func (a *Auth) LoadSession(next http.Handler) http.Handler

LoadSession attaches the session and the user when the request carries a valid one, and calls next either way.

Use LoadSession for a route that serves an anonymous visitor and a signed-in user from one handler. The handler tests the result with UserFrom.

A storage failure never blocks the request. LoadSession logs it and treats the request as anonymous.

func (*Auth) LoadSessionFunc added in v0.2.0

func (a *Auth) LoadSessionFunc(next http.HandlerFunc) http.Handler

LoadSessionFunc is the http.HandlerFunc form of LoadSession.

func (*Auth) Migrate

func (a *Auth) Migrate(ctx context.Context) ([]schema.Statement, error)

Migrate applies the effective schema. It runs only when the application or the command line tool calls it.

func (*Auth) MigrationPlan

func (a *Auth) MigrationPlan(ctx context.Context) ([]schema.Statement, error)

MigrationPlan returns the statements that are not applied yet.

func (*Auth) MigrationSQL

func (a *Auth) MigrationSQL(d schema.Dialect) ([]schema.Statement, error)

MigrationSQL returns the complete deterministic DDL for one dialect. It needs no database connection.

func (*Auth) OpenAPI

func (a *Auth) OpenAPI() *openapi.Document

OpenAPI returns the effective OpenAPI document of the enabled API.

func (*Auth) RequireAuth added in v0.2.0

func (a *Auth) RequireAuth(next http.Handler) http.Handler

RequireAuth protects an application route. It resolves the session one time, puts the session and the user in the request context, and calls next.

A request with no valid session never reaches next. RequireAuth answers it with the Auth-All error contract and status 401.

mux.Handle("/api/me", auth.RequireAuth(meHandler))

The handler reads the result with SessionFrom and UserFrom, which cost no second database lookup.

func (*Auth) RequireAuthFunc added in v0.2.0

func (a *Auth) RequireAuthFunc(next http.HandlerFunc) http.Handler

RequireAuthFunc is the http.HandlerFunc form of RequireAuth.

func (*Auth) RevokeOtherSessions added in v0.3.0

func (a *Auth) RevokeOtherSessions(ctx context.Context, sessionID string) (int, error)

RevokeOtherSessions removes every session of the owner of sessionID, except that session. It returns the number of removed sessions.

The session that the caller names stays valid, so the person keeps the current browser and loses every other one.

func (*Auth) RevokeSession

func (a *Auth) RevokeSession(ctx context.Context, sessionID string) error

RevokeSession revokes one session by id.

func (*Auth) RevokeUserSessions

func (a *Auth) RevokeUserSessions(ctx context.Context, userID string) (int, error)

RevokeUserSessions revokes every session of one user and returns the count.

func (*Auth) RoleAtLeast added in v0.3.0

func (a *Auth) RoleAtLeast(role, min string) bool

RoleAtLeast reports whether role ranks equal to or above min. A role that the configuration does not name ranks below every role, which is default deny.

func (*Auth) RoleNames added in v0.3.0

func (a *Auth) RoleNames() []string

RoleNames returns the configured roles from the lowest to the highest. It is empty when no roles plugin is enabled.

func (*Auth) Routes

func (a *Auth) Routes() []RouteInfo

Routes returns every mounted route of the enabled API.

func (*Auth) Schema

func (a *Auth) Schema() *schema.Schema

Schema returns the effective schema of core plus every registered plugin.

func (*Auth) Session

func (a *Auth) Session(ctx context.Context, r *http.Request) (*store.Session, error)

Session returns the session of a request. It returns nil when the request carries no valid session.

func (*Auth) SetSessionCookie added in v0.4.0

func (a *Auth) SetSessionCookie(w http.ResponseWriter, token string, expiresAt time.Time)

SetSessionCookie writes the session cookie of one token. A host that serves a browser calls it with the token of a SignInResult.

func (*Auth) SignIn added in v0.4.0

func (a *Auth) SignIn(ctx context.Context, in SignInInput) (*SignInResult, error)

SignIn verifies an email address and a password.

It returns a session, or a challenge when the user holds a confirmed second factor. It writes no cookie and no response, so the caller owns the transport. SetSessionCookie writes the cookie of a browser.

An unknown address and a wrong password give one error, and they cost equal work, so neither the response nor the response time discloses whether the account exists.

func (*Auth) SignOut added in v0.4.0

func (a *Auth) SignOut(ctx context.Context, session *store.Session) error

SignOut ends one session.

It runs the sign-out hook and emits the audit event, which RevokeSession does not. A nil session and a session that is already gone are no error, so a repeated sign-out is safe. The caller removes the cookie with ClearSessionCookie.

func (*Auth) SignOutToken added in v0.4.0

func (a *Auth) SignOutToken(ctx context.Context, token string) error

SignOutToken ends the session of one plaintext session token. An unknown token is no error, so a repeated sign-out is safe.

func (*Auth) Store added in v0.3.0

func (a *Auth) Store() store.Store

Store returns the configured storage adapter. The application owns it.

func (*Auth) User

func (a *Auth) User(ctx context.Context, r *http.Request) (*store.User, error)

User returns the authenticated user of a request. It returns nil when the request carries no valid session.

func (*Auth) UserFields added in v0.3.0

func (a *Auth) UserFields() []schema.UserField

UserFields returns the declared host-owned user fields.

func (*Auth) VerifyEmailToken

func (a *Auth) VerifyEmailToken(ctx context.Context, token string) (*store.User, error)

VerifyEmailToken consumes an email verification token and records that the user controls the address. It exists so an application can verify an address from its own page without a call to the HTTP API.

type ChangePasswordInput added in v0.4.0

type ChangePasswordInput struct {
	// UserID is the owner of the password.
	UserID string
	// CurrentPassword is the password of the account. The change needs it, so
	// a stolen session alone cannot replace a password.
	CurrentPassword string
	// NewPassword must meet the configured password policy.
	NewPassword string
	// KeepSessionID keeps one session when the change revokes the others. The
	// caller names the session of the request here.
	KeepSessionID string
	// KeepOtherSessions keeps every other session of the user. The zero value
	// revokes them, because a password change must end a stolen session.
	KeepOtherSessions bool
	// ClientIP is the address of the caller. The rate limit counts the attempt
	// against it.
	ClientIP string
}

ChangePasswordInput names one password change of the owner of the account.

type Code

type Code = apierr.Code

Code is a stable machine-readable error code.

type CookieOptions

type CookieOptions struct {
	Name     string
	Domain   string
	Path     string
	SameSite http.SameSite
	// Secure defaults to true. Set it to false only for local development
	// over plain HTTP.
	Secure *bool
}

CookieOptions configures the session cookie.

type CreateUserInput

type CreateUserInput struct {
	Email       string
	Password    string
	DisplayName string
	ImageURL    string
	// EmailVerified marks the address as already proven.
	EmailVerified bool
	// Extra holds the host-owned user fields. A field that the host did not
	// declare is dropped.
	//
	// The field is a pointer, so a CreateUserInput value stays comparable.
	Extra *store.ExtraFields
}

CreateUserInput describes a user created through the programmatic API.

type EmailPasswordOptions

type EmailPasswordOptions struct {
	// RequireEmailVerification blocks sign-in until the address is verified.
	RequireEmailVerification bool
	// SendVerificationOnSignUp sends a verification email after sign-up. It is
	// implied by RequireEmailVerification.
	SendVerificationOnSignUp bool
	// VerifyEmailURL is the application page that receives a verification
	// token. Auth-All appends the token query parameter. The default is
	// BaseURL + /verify-email.
	VerifyEmailURL string
	// ResetPasswordURL is the application page that receives a password reset
	// token. Auth-All appends the token query parameter. The default is
	// BaseURL + /reset-password.
	ResetPasswordURL string
	// ChangeEmailURL is the application page that receives an email change
	// token. Auth-All appends the token query parameter. The default is
	// BaseURL + /change-email.
	ChangeEmailURL string
	// DeleteAccountURL is the application page that receives an account delete
	// token. Auth-All appends the token query parameter. The default is
	// BaseURL + /delete-account.
	DeleteAccountURL string
}

EmailPasswordOptions configures email and password authentication.

type Error

type Error = apierr.Error

Error is the public Auth-All error type. Its code is part of the public API compatibility surface.

type Option

type Option func(*config)

Option configures Auth-All.

func WithAccountLinking

func WithAccountLinking(o AccountLinkingOptions) Option

WithAccountLinking configures the account linking policy.

func WithArgon2Params

func WithArgon2Params(p crypto.Argon2Params) Option

WithArgon2Params configures the password hashing cost. A sign-in rehashes a password that was stored with different parameters.

func WithBasePath

func WithBasePath(p string) Option

WithBasePath sets the mount path of the HTTP handler. The default is /api/auth.

func WithBaseURL

func WithBaseURL(u string) Option

WithBaseURL sets the absolute public URL of the application, for example https://app.example.com. Auth-All uses it to build links and to validate redirects. It is required when an OAuth provider is configured.

func WithClock

func WithClock(now func() time.Time) Option

WithClock replaces the clock. Tests use it for deterministic expiry.

func WithConsistencyBound added in v0.3.0

func WithConsistencyBound(d time.Duration) Option

WithConsistencyBound sets the maximum time between a committed change and its effect on every instance. The default is 5 seconds.

Auth-All keeps no authorization state in memory past this time.

func WithCookie

func WithCookie(o CookieOptions) Option

WithCookie configures the session cookie.

func WithCookieSameSite

func WithCookieSameSite(mode http.SameSite) Option

WithCookieSameSite sets the SameSite attribute of the session cookie.

Use http.SameSiteLaxMode when the application and the API share a registrable domain, for example app.example.com and api.example.com. Use http.SameSiteNoneMode only for a true cross-site setup. A browser refuses a cookie with SameSite=None and no Secure attribute, so that pair fails the construction. See docs/guides/deployment.md.

func WithEmailPassword

func WithEmailPassword(opts ...EmailPasswordOptions) Option

WithEmailPassword enables email and password authentication.

func WithEmailSender

func WithEmailSender(s email.Sender) Option

WithEmailSender sets the email delivery boundary of the application.

func WithErrorWriter added in v0.3.0

func WithErrorWriter(f func(w http.ResponseWriter, r *http.Request, e *Error)) Option

WithErrorWriter replaces the public error envelope of every Auth-All route, of RequireAuth, of LoadSession, and of every plugin route.

The writer receives the public error only. Auth-All keeps the private cause in its log. The writer must keep a header that the status needs, for example Retry-After on status 429.

func WithEventHandler

func WithEventHandler(h events.Handler) Option

WithEventHandler registers an observability handler.

func WithHostOriginCheck added in v0.3.0

func WithHostOriginCheck(on bool) Option

WithHostOriginCheck turns the origin check of the host routes on or off. The default is on.

RequireAuth, LoadSession, and a role check refuse an unsafe cross-site request that a cookie authenticated. A bearer request skips the check, because a cross-site page cannot send a bearer credential.

Turn the check off only when another layer already refuses a cross-site request. Auth-All writes a warn-level log entry when the check is off.

func WithLogger

func WithLogger(l *slog.Logger) Option

WithLogger sets the logger.

func WithOrganizationFields added in v0.4.0

func WithOrganizationFields(fields ...schema.UserField) Option

WithOrganizationFields adds host-owned columns to the organizations table. It appends to the fields of WithSchema. The columns apply only when the organizations plugin is enabled.

func WithPasswordPolicy

func WithPasswordPolicy(p PasswordPolicy) Option

WithPasswordPolicy configures the accepted passwords.

func WithPlugins

func WithPlugins(plugins ...plugin.Plugin) Option

WithPlugins registers one or more plugins.

func WithPrincipalCache added in v0.3.0

func WithPrincipalCache(ttl time.Duration) Option

WithPrincipalCache keeps a resolved principal in process memory for ttl.

The cache saves one store round trip for each request. Construction fails when ttl is above the consistency bound, because a longer entry would keep a disabled user, a demoted user, or a revoked credential alive past the bound.

The cache is off by default. With no cache, every request reads the store, so the effective bound is zero.

func WithProvider

func WithProvider(providers ...oauth.Provider) Option

WithProvider registers one or more OAuth providers.

func WithRateLimiter

func WithRateLimiter(l ratelimit.Limiter) Option

WithRateLimiter sets the rate limiter for sensitive operations.

func WithSchema added in v0.3.0

func WithSchema(o schema.Options) Option

WithSchema configures the physical schema. It sets the table prefix, the identifier type, and the host-owned user fields. The store must accept the same options, so Auth-All passes them to a first-party store.

func WithSchemaCheck added in v0.3.0

func WithSchemaCheck(m SchemaCheckMode) Option

WithSchemaCheck selects the source that CheckSchema reads.

func WithSession

func WithSession(o SessionOptions) Option

WithSession configures session lifetime.

func WithSessionLifetime

func WithSessionLifetime(idle, absolute time.Duration) Option

WithSessionLifetime sets the two session deadlines.

idle ends a session that saw no request for that long. absolute ends a session at that age, even when the person stays active. One value cannot serve both, because a stolen token that stays active would never expire.

The defaults are 7 days and 30 days.

func WithStore

func WithStore(s store.Store) Option

WithStore sets the storage adapter. It is required.

func WithStrictOriginCheck added in v0.4.0

func WithStrictOriginCheck() Option

WithStrictOriginCheck refuses an unsafe request that carries the session cookie and names no origin.

Auth-All and the Go standard library pass a request that sends neither an Origin header nor a Sec-Fetch-Site header, because a client that is not a browser sends neither, and it carries no ambient credential. A browser sends at least one of the two. This option therefore refuses a cookie request that sends none of them, and it refuses an opaque origin, because "null" is never a trusted origin.

Turn it on when every cookie client is a browser. A cookie client that is no browser, for example a script that keeps a cookie jar, then gets 403 ORIGIN_NOT_ALLOWED. A bearer client is never affected, because a cross-site page cannot send a bearer credential.

The option changes no behavior of a GET, a HEAD, or an OPTIONS request.

func WithStrictRateLimiting

func WithStrictRateLimiting() Option

WithStrictRateLimiting fails the construction when no rate limiter is configured.

A production deployment needs a limiter. Without one, every sensitive endpoint accepts unlimited attempts, so a brute-force attack and an enumeration attack run without a bound. The default only writes a warning, because a test and a local run do not need a limiter.

func WithTOTP added in v0.2.0

func WithTOTP(opts ...TOTPOptions) Option

WithTOTP enables the time-based one-time password second factor.

The endpoints /totp/enrol, /totp/confirm, and /totp/disable appear. A user who confirms an enrolment must supply a code at every later sign-in.

func WithTokenTTL

func WithTokenTTL(o TokenTTLOptions) Option

WithTokenTTL configures one-time token lifetimes.

func WithTrustedOrigins

func WithTrustedOrigins(origins ...string) Option

WithTrustedOrigins adds browser origins that can call state-changing endpoints. The origin of BaseURL is always trusted. A credentialed wildcard origin is never allowed.

func WithTrustedProxies

func WithTrustedProxies(cidrs ...string) Option

WithTrustedProxies declares the reverse proxies that stand in front of the application. Auth-All reads a forwarded client address only when the direct peer is inside one of these blocks.

Each value is a CIDR block, for example 10.0.0.0/8. A single IP address is also valid, and Auth-All treats it as one host. An invalid value fails the construction.

Auth-All ignores the X-Forwarded-For header when no trusted proxy is declared, because any client can set that header. Declare the proxies of the deployment. See docs/guides/deployment.md.

func WithUserFields added in v0.3.0

func WithUserFields(fields ...schema.UserField) Option

WithUserFields adds host-owned columns to the users table. It appends to the fields of WithSchema.

type PasswordPolicy

type PasswordPolicy struct {
	MinLength int
	MaxLength int
}

PasswordPolicy configures the accepted passwords. Auth-All does not require special characters, because a length requirement protects better.

func DefaultPasswordPolicy

func DefaultPasswordPolicy() PasswordPolicy

DefaultPasswordPolicy returns the default policy.

type Principal added in v0.3.0

type Principal struct {
	// User is the owner of the credential. It is never nil.
	User *store.User
	// Session is nil for an API key request.
	Session *store.Session
	// APIKey is nil for a session request.
	APIKey *store.APIKey
	// Role is the effective role of the request.
	Role string
	// Method is MethodSession or MethodAPIKey.
	Method string
	// ViaCookie reports whether a cookie carried the credential. Only a cookie
	// request needs the origin check.
	ViaCookie bool
	// Organization is the active organization of the session. It is nil when
	// the session names none, and when the organizations plugin is off.
	Organization *store.Organization
	// Membership is the membership of the active organization. It is nil when
	// no organization is active, and when the membership is gone. Its
	// Permissions field holds the statements that the credential read
	// resolved, for a custom role and for every team role of the member.
	Membership *store.Membership
}

Principal is the authenticated caller of one request.

func PrincipalFrom added in v0.3.0

func PrincipalFrom(ctx context.Context) *Principal

PrincipalFrom returns the principal that RequireAuth, LoadSession, or a role check attached to the request context. It returns nil for any other context.

type RateLimitError added in v0.4.0

type RateLimitError struct {
	// RetryAfter is the time until the next attempt. A limiter that names none
	// gives one minute.
	RetryAfter time.Duration
}

RateLimitError reports a refused attempt and the time to wait. It wraps apierr.ErrRateLimited, so a caller that maps the public error contract keeps the code RATE_LIMITED.

func (*RateLimitError) Error added in v0.4.0

func (e *RateLimitError) Error() string

Error implements the error interface.

func (*RateLimitError) Unwrap added in v0.4.0

func (e *RateLimitError) Unwrap() error

Unwrap returns the public error of the contract.

type RouteInfo

type RouteInfo struct {
	Method string
	// Path is the complete path, including the configured base path.
	Path string
	// PluginID names the contributing plugin. It is empty for a core route.
	PluginID string
	// Documented reports whether the route appears in the OpenAPI document.
	Documented bool
}

RouteInfo describes one mounted Auth-All route.

type SchemaCheckMode added in v0.3.0

type SchemaCheckMode int

SchemaCheckMode selects how CheckSchema reads the state of the database.

const (
	// SchemaCheckRecord compares the Auth-All record table with the effective
	// schema. It is the default, and it fits an application that calls
	// Migrate.
	SchemaCheckRecord SchemaCheckMode = iota
	// SchemaCheckCatalog reads the database catalog. A host that applies the
	// exported migrations with its own tool writes no Auth-All record, so the
	// catalog is the only source of truth.
	SchemaCheckCatalog
)

type SchemaContributor added in v0.3.0

type SchemaContributor interface {
	// SchemaTables returns the tables of the contributor.
	SchemaTables(o schema.Options) []schema.Table
	// SchemaUnits returns the migration units of the contributor.
	SchemaUnits(o schema.Options) ([]schema.Unit, error)
}

SchemaContributor is an optional interface of a component that owns a table, for example the store-backed rate limiter. Auth-All adds the tables and the migration units of a contributor to the effective schema.

type SessionOptions

type SessionOptions struct {
	// TTL is the absolute lifetime. A session ends at this age, even when the
	// person stays active. The default is 30 days.
	TTL time.Duration
	// IdleTimeout ends a session that saw no request for this long. The
	// default is 7 days.
	IdleTimeout time.Duration
	// TouchInterval limits how often a session read updates last_seen_at.
	TouchInterval time.Duration
}

SessionOptions configures session lifetime.

type SignInInput added in v0.4.0

type SignInInput struct {
	// Email is the address of the account. The comparison uses the normalized
	// form.
	Email string
	// Password is the plaintext password of the attempt.
	Password string
	// ClientIP is the address of the caller. The rate limit counts the attempt
	// against it. An empty value counts the address only.
	ClientIP string
	// PreviousSessionToken names a session of the caller that the sign-in
	// replaces. The HTTP route passes the token of the request, so no old
	// session survives a new sign-in.
	PreviousSessionToken string
}

SignInInput names one password sign-in.

type SignInResult added in v0.4.0

type SignInResult struct {
	// User is the account of the sign-in. It is never nil on success.
	User *store.User
	// Session is the new session. It is nil when a second factor is required.
	Session *store.Session
	// Token is the plaintext session token. It exists one time, here. A host
	// that serves a browser writes it with SetSessionCookie. A host that
	// serves a bearer client returns it to the client.
	Token string
	// MFARequired reports that the user holds a confirmed second factor. No
	// session exists until the second proof.
	MFARequired bool
	// MFAToken is the challenge of the second factor. It is empty when no
	// second factor is required.
	MFAToken string
}

SignInResult is the outcome of one password sign-in.

type TOTPOptions added in v0.2.0

type TOTPOptions struct {
	// Issuer is the name that the authenticator application shows. It defaults
	// to the host of the base URL.
	Issuer string
}

TOTPOptions configures the time-based one-time password second factor.

type TokenTTLOptions

type TokenTTLOptions struct {
	EmailVerification time.Duration
	PasswordReset     time.Duration
	OAuthState        time.Duration
}

TokenTTLOptions configures one-time token lifetimes.

Directories

Path Synopsis
Package apierr defines the stable, machine-readable error contract of Auth-All.
Package apierr defines the stable, machine-readable error contract of Auth-All.
cmd
auth-all command
Command auth-all manages the Auth-All schema and generates the published contract artifacts.
Command auth-all manages the Auth-All schema and generates the published contract artifacts.
Package email defines the provider-independent email boundary of Auth-All.
Package email defines the provider-independent email boundary of Auth-All.
Package events defines the structured observability events of Auth-All.
Package events defines the structured observability events of Auth-All.
examples
go-app command
Command example-app shows a complete Auth-All integration in a small Go application.
Command example-app shows a complete Auth-All integration in a small Go application.
Package hook defines the typed lifecycle hooks of Auth-All.
Package hook defines the typed lifecycle hooks of Auth-All.
humaauth module
internal
clientgen
Package clientgen generates the official TypeScript client from the effective OpenAPI document.
Package clientgen generates the official TypeScript client from the effective OpenAPI document.
crypto
Package crypto holds the password hashing and token primitives of Auth-All.
Package crypto holds the password hashing and token primitives of Auth-All.
jwt
Package jwt verifies the compact RS256 identity tokens of OpenID Connect providers.
Package jwt verifies the compact RS256 identity tokens of OpenID Connect providers.
reference
Package reference builds the canonical Auth-All configuration.
Package reference builds the canonical Auth-All configuration.
sqlstore
Package sqlstore implements the Auth-All storage boundary over database/sql.
Package sqlstore implements the Auth-All storage boundary over database/sql.
testsupport
Package testsupport builds migrated databases for the Auth-All test suites.
Package testsupport builds migrated databases for the Auth-All test suites.
totp
Package totp implements the time-based one-time password of RFC 6238 over the HMAC one-time password of RFC 4226.
Package totp implements the time-based one-time password of RFC 6238 over the HMAC one-time password of RFC 4226.
Package migrations exports the Auth-All migration units as files.
Package migrations exports the Auth-All migration units as files.
Package oauth defines the OAuth provider boundary of Auth-All.
Package oauth defines the OAuth provider boundary of Auth-All.
github
Package github implements the GitHub OAuth provider for Auth-All.
Package github implements the GitHub OAuth provider for Auth-All.
google
Package google implements the Google OpenID Connect provider for Auth-All.
Package google implements the Google OpenID Connect provider for Auth-All.
oidc
Package oidc implements a generic OpenID Connect provider for Auth-All.
Package oidc implements a generic OpenID Connect provider for Auth-All.
Package openapi holds the OpenAPI document model of Auth-All.
Package openapi holds the OpenAPI document model of Auth-All.
Package plugin is the public extension surface of Auth-All.
Package plugin is the public extension surface of Auth-All.
plugins
admin
Package admin adds user administration to Auth-All.
Package admin adds user administration to Auth-All.
apikeys
Package apikeys adds machine credentials to Auth-All.
Package apikeys adds machine credentials to Auth-All.
magiclink
Package magiclink implements sign-in through an emailed one-time link.
Package magiclink implements sign-in through an emailed one-time link.
organizations
Package organizations adds organizations, memberships, and fine-grained permissions to Auth-All.
Package organizations adds organizations, memberships, and fine-grained permissions to Auth-All.
organizations/permission
Package permission holds the permission statements of Auth-All.
Package permission holds the permission statements of Auth-All.
roles
Package roles adds a host-defined role hierarchy to Auth-All.
Package roles adds a host-defined role hierarchy to Auth-All.
Package ratelimit defines the rate-limit integration point of Auth-All.
Package ratelimit defines the rate-limit integration point of Auth-All.
storelimit
Package storelimit is a rate limiter that keeps its counters in the Auth-All database.
Package storelimit is a rate limiter that keeps its counters in the Auth-All database.
Package schema describes the Auth-All database schema independently from a specific database engine.
Package schema describes the Auth-All database schema independently from a specific database engine.
Package store defines the storage boundary of Auth-All.
Package store defines the storage boundary of Auth-All.
postgres
Package postgres provides the PostgreSQL storage adapter for Auth-All.
Package postgres provides the PostgreSQL storage adapter for Auth-All.
sqlite
Package sqlite provides the SQLite storage adapter for Auth-All.
Package sqlite provides the SQLite storage adapter for Auth-All.
storetest
Package storetest holds the behavioral contract suite that every Auth-All storage adapter must pass.
Package storetest holds the behavioral contract suite that every Auth-All storage adapter must pass.
tools
coverage command
Command coverage reports the statement coverage of one package set.
Command coverage reports the statement coverage of one package set.
evidence command
Command evidence writes the verification evidence of Auth-All.
Command evidence writes the verification evidence of Auth-All.

Jump to

Keyboard shortcuts

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