Documentation
¶
Overview ¶
Package auth provides authentication as a burrow contrib app.
It implements WebAuthn (passkeys), recovery codes, email verification, and invite-only registration. Context helpers provide access to the authenticated user from any handler.
Index ¶
- Constants
- Variables
- func DefaultAuthLayout() string
- func DefaultEmailRenderer() authmail.Renderer
- func GenerateInviteToken() (plaintext, hash string, err error)
- func GenerateToken() (string, string, time.Time, error)
- func HashToken(token string) string
- func IsAuthenticated(ctx context.Context) bool
- func Logo(ctx context.Context) template.HTML
- func LogoFromContext(ctx context.Context) template.HTML
- func NormalizeCode(code string) string
- func RequireAdmin() func(http.Handler) http.Handler
- func RequireAuth() func(http.Handler) http.Handler
- func SafeRedirectPath(next, defaultPath string) string
- func TransportsFromWebAuthn(transports []protocol.AuthenticatorTransport) string
- func WithLogo(ctx context.Context, logo template.HTML) context.Context
- func WithUser(ctx context.Context, user *User) context.Context
- type App
- func (a *App) AcknowledgeRecoveryCodes(w http.ResponseWriter, r *http.Request) error
- func (a *App) AddCredentialBegin(w http.ResponseWriter, r *http.Request) error
- func (a *App) AddCredentialFinish(w http.ResponseWriter, r *http.Request) error
- func (a *App) AdminNavItems() []burrow.NavItem
- func (a *App) AdminRoutes(r chi.Router)
- func (a *App) CLICommands() []*cli.Command
- func (a *App) Configure(cfg *burrow.AppConfig, cmd *cli.Command) error
- func (a *App) CredentialsPage(w http.ResponseWriter, r *http.Request) error
- func (a *App) DeleteCredential(w http.ResponseWriter, r *http.Request) error
- func (a *App) Dependencies() []string
- func (a *App) Documents() []any
- func (a *App) Flags(configSource func(key string) cli.ValueSource) []cli.Flag
- func (a *App) FuncMap() template.FuncMap
- func (a *App) IsInviteOnly() bool
- func (a *App) LoginBegin(w http.ResponseWriter, r *http.Request) error
- func (a *App) LoginFinish(w http.ResponseWriter, r *http.Request) error
- func (a *App) LoginPage(w http.ResponseWriter, r *http.Request) error
- func (a *App) Logout(w http.ResponseWriter, r *http.Request) error
- func (a *App) Middleware() []func(http.Handler) http.Handler
- func (a *App) Name() string
- func (a *App) RecoveryCodesPage(w http.ResponseWriter, r *http.Request) error
- func (a *App) RecoveryLogin(w http.ResponseWriter, r *http.Request) error
- func (a *App) RecoveryPage(w http.ResponseWriter, r *http.Request) error
- func (a *App) RegenerateRecoveryCodes(w http.ResponseWriter, r *http.Request) error
- func (a *App) RegisterBegin(w http.ResponseWriter, r *http.Request) error
- func (a *App) RegisterFinish(w http.ResponseWriter, r *http.Request) error
- func (a *App) RegisterJobs(q burrow.Queue)
- func (a *App) RegisterPage(w http.ResponseWriter, r *http.Request) error
- func (a *App) Repo() *Repository
- func (a *App) RequestFuncMap(ctx context.Context) template.FuncMap
- func (a *App) RequireAdmin() func(http.Handler) http.Handler
- func (a *App) RequireAuth() func(http.Handler) http.Handler
- func (a *App) ResendVerification(w http.ResponseWriter, r *http.Request) error
- func (a *App) Routes(r chi.Router)
- func (a *App) Shutdown(_ context.Context) error
- func (a *App) Start(_ *burrow.Server) error
- func (a *App) StaticFS() (string, fs.FS)
- func (a *App) TemplateFS() fs.FS
- func (a *App) TranslationFS() fs.FS
- func (a *App) UseEmailMode() bool
- func (a *App) VerifyEmail(w http.ResponseWriter, r *http.Request) error
- func (a *App) VerifyPendingPage(w http.ResponseWriter, r *http.Request) error
- type Config
- type CreateInviteRequest
- type Credential
- type EmailService
- type EmailVerificationToken
- type Invite
- type Option
- type RecoveryCode
- type RecoveryLoginRequest
- type RecoveryService
- type RegisterBeginRequest
- type Renderer
- type Repository
- func (r *Repository) CountAdminUsers(ctx context.Context) (int, error)
- func (r *Repository) CountUserCredentials(ctx context.Context, userID string) (int64, error)
- func (r *Repository) CountUsers(ctx context.Context) (int, error)
- func (r *Repository) CreateCredential(ctx context.Context, cred *Credential) error
- func (r *Repository) CreateEmailVerificationToken(ctx context.Context, userID string, tokenHash string, expiresAt time.Time) error
- func (r *Repository) CreateInvite(ctx context.Context, invite *Invite) error
- func (r *Repository) CreateRecoveryCodes(ctx context.Context, userID string, codeHashes []string) error
- func (r *Repository) CreateUser(ctx context.Context, username, name string) (*User, error)
- func (r *Repository) CreateUserWithEmail(ctx context.Context, email, name string) (*User, error)
- func (r *Repository) DeleteCredential(ctx context.Context, credID, userID string) error
- func (r *Repository) DeleteEmailVerificationToken(ctx context.Context, tokenID string) error
- func (r *Repository) DeleteExpiredEmailVerificationTokens(ctx context.Context) error
- func (r *Repository) DeleteInvite(ctx context.Context, inviteID string) error
- func (r *Repository) DeleteRecoveryCodes(ctx context.Context, userID string) error
- func (r *Repository) DeleteUser(ctx context.Context, id string) error
- func (r *Repository) DeleteUserEmailVerificationTokens(ctx context.Context, userID string) error
- func (r *Repository) EmailExists(ctx context.Context, email string) (bool, error)
- func (r *Repository) GetCredentialsByUserID(ctx context.Context, userID string) ([]Credential, error)
- func (r *Repository) GetEmailVerificationToken(ctx context.Context, tokenHash string) (*EmailVerificationToken, error)
- func (r *Repository) GetInviteByID(ctx context.Context, id string) (*Invite, error)
- func (r *Repository) GetInviteByTokenHash(ctx context.Context, tokenHash string) (*Invite, error)
- func (r *Repository) GetUnusedRecoveryCodeCount(ctx context.Context, userID string) (int64, error)
- func (r *Repository) GetUnusedRecoveryCodes(ctx context.Context, userID string) ([]RecoveryCode, error)
- func (r *Repository) GetUserByEmail(ctx context.Context, email string) (*User, error)
- func (r *Repository) GetUserByID(ctx context.Context, id string) (*User, error)
- func (r *Repository) GetUserByIDWithCredentials(ctx context.Context, id string) (*User, error)
- func (r *Repository) GetUserByUsername(ctx context.Context, username string) (*User, error)
- func (r *Repository) HasRecoveryCodes(ctx context.Context, userID string) (bool, error)
- func (r *Repository) ListInvites(ctx context.Context) ([]Invite, error)
- func (r *Repository) ListInvitesPaged(ctx context.Context, pr burrow.PageRequest) ([]Invite, burrow.PageResult, error)
- func (r *Repository) ListUsers(ctx context.Context) ([]User, error)
- func (r *Repository) ListUsersPaged(ctx context.Context, pr burrow.PageRequest, role string) ([]User, burrow.PageResult, error)
- func (r *Repository) MarkEmailVerified(ctx context.Context, userID string) error
- func (r *Repository) MarkInviteUsed(ctx context.Context, inviteID, userID string) error
- func (r *Repository) MarkRecoveryCodeUsed(ctx context.Context, codeID string) error
- func (r *Repository) PurgeOrphanedUsers(ctx context.Context, olderThan time.Duration) (int, error)
- func (r *Repository) SearchInvitesPaged(ctx context.Context, query string, pr burrow.PageRequest) ([]Invite, burrow.PageResult, error)
- func (r *Repository) SearchUsers(ctx context.Context, query string, pr burrow.PageRequest, role string) ([]User, burrow.PageResult, error)
- func (r *Repository) SetUserActive(ctx context.Context, userID string, active bool) error
- func (r *Repository) SetUserRole(ctx context.Context, userID string, role string) error
- func (r *Repository) UpdateCredentialSignCount(ctx context.Context, credentialID []byte, signCount uint32) error
- func (r *Repository) UpdateUser(ctx context.Context, user *User) error
- func (r *Repository) UserExists(ctx context.Context, username string) (bool, error)
- func (r *Repository) ValidateAndUseRecoveryCode(ctx context.Context, userID string, code string) (bool, error)
- type ResendVerificationRequest
- type User
- type WebAuthnService
Examples ¶
Constants ¶
const ( RoleUser = "user" RoleAdmin = "admin" )
Role constants.
const ( // TokenLength is the number of random bytes for verification tokens. TokenLength = 32 // TokenExpiry is how long verification tokens are valid. TokenExpiry = 24 * time.Hour // InviteExpiry is how long an invite token is valid. InviteExpiry = 7 * 24 * time.Hour )
const ( // CodeLength is the length of each recovery code (without dashes). CodeLength = 12 // CodeCount is the default number of recovery codes to generate. CodeCount = 8 )
Variables ¶
var ErrInviteAlreadyUsed = errors.New("invite already used")
ErrInviteAlreadyUsed is returned when an invite has already been consumed.
var ErrNotFound = den.ErrNotFound
ErrNotFound is returned when a record is not found.
Functions ¶
func DefaultAuthLayout ¶
func DefaultAuthLayout() string
DefaultAuthLayout returns the template name for the built-in auth layout. Uses the base µCSS layout directly.
func DefaultEmailRenderer ¶
DefaultEmailRenderer returns a Renderer that uses the built-in HTML email templates with i18n support. When a localizer is present in the context (via i18n middleware or i18n.App.WithLocale), all strings are translated. Without a localizer, translation keys are returned as-is.
func GenerateInviteToken ¶
GenerateInviteToken generates a random invite token and its SHA256 hash.
func GenerateToken ¶
GenerateToken generates a new verification token. Returns (plaintext token, SHA256 hash for storage, expiry time, error).
func IsAuthenticated ¶
IsAuthenticated returns true if a user is present in the context.
Example ¶
package main
import (
"context"
"fmt"
"github.com/oliverandrich/burrow/contrib/auth"
)
func main() {
// No user in context — not authenticated.
fmt.Println(auth.IsAuthenticated(context.Background()))
// With a user in context — authenticated.
ctx := auth.WithUser(context.Background(), &auth.User{Username: "bob"})
fmt.Println(auth.IsAuthenticated(ctx))
}
Output: false true
func LogoFromContext ¶
LogoFromContext is a deprecated alias for Logo.
func NormalizeCode ¶
NormalizeCode removes dashes and converts to lowercase for comparison.
Example ¶
package main
import (
"fmt"
"github.com/oliverandrich/burrow/contrib/auth"
)
func main() {
fmt.Println(auth.NormalizeCode("ABCD-EFGH-2345"))
}
Output: abcdefgh2345
func RequireAdmin ¶
RequireAdmin returns middleware that enforces admin access. Unauthenticated users are redirected to login (like RequireAuth). Authenticated non-admin users see a 403 error page.
func RequireAuth ¶
RequireAuth returns middleware that redirects to login if not authenticated. The original request URL is stored in the session as "redirect_after_login" so the user can be redirected back after successful authentication.
For GET requests, the full request URI is stored. For other methods (POST, PUT, DELETE, etc.), the Referer header is used instead — since the redirect back is always a GET, storing a POST-only URL would cause a 405.
func SafeRedirectPath ¶
SafeRedirectPath validates a redirect path, falling back to defaultPath.
Example ¶
package main
import (
"fmt"
"github.com/oliverandrich/burrow/contrib/auth"
)
func main() {
// A relative path is accepted as-is.
fmt.Println(auth.SafeRedirectPath("/profile", "/"))
// An absolute URL with a host is rejected.
fmt.Println(auth.SafeRedirectPath("https://evil.example.com", "/"))
// An empty string falls back to the default.
fmt.Println(auth.SafeRedirectPath("", "/home"))
}
Output: /profile / /home
func TransportsFromWebAuthn ¶
func TransportsFromWebAuthn(transports []protocol.AuthenticatorTransport) string
TransportsFromWebAuthn converts WebAuthn transports to a comma-separated string.
Types ¶
type App ¶
type App struct {
// contains filtered or unexported fields
}
App implements the auth contrib app.
func New ¶
New creates a new auth app with the given options. By default, the built-in HTML renderer and auth layout are used. Use WithRenderer() and WithAuthLayout() to override.
func (*App) AcknowledgeRecoveryCodes ¶ added in v0.11.0
AcknowledgeRecoveryCodes clears recovery codes from the session and redirects.
func (*App) AddCredentialBegin ¶ added in v0.11.0
AddCredentialBegin starts the process of adding a new credential.
func (*App) AddCredentialFinish ¶ added in v0.11.0
AddCredentialFinish completes adding a new credential.
func (*App) AdminNavItems ¶
AdminNavItems returns navigation items for the admin panel.
func (*App) AdminRoutes ¶
AdminRoutes registers admin routes for user and invite management. The router is expected to already have auth middleware applied.
func (*App) CLICommands ¶
CLICommands returns auth-related CLI subcommands (promote, demote, create-invite).
func (*App) CredentialsPage ¶ added in v0.11.0
CredentialsPage renders the credentials management page.
func (*App) DeleteCredential ¶ added in v0.11.0
DeleteCredential removes a credential.
func (*App) Dependencies ¶
func (*App) Documents ¶ added in v0.11.0
Documents returns the Den document types registered by this app.
func (*App) IsInviteOnly ¶ added in v0.11.0
IsInviteOnly returns true if invite-only registration is enabled.
func (*App) LoginBegin ¶ added in v0.11.0
LoginBegin starts the WebAuthn discoverable login process.
func (*App) LoginFinish ¶ added in v0.11.0
LoginFinish completes the WebAuthn discoverable login.
func (*App) RecoveryCodesPage ¶ added in v0.11.0
RecoveryCodesPage renders the dedicated recovery codes page.
func (*App) RecoveryLogin ¶ added in v0.11.0
RecoveryLogin authenticates a user with a recovery code.
func (*App) RecoveryPage ¶ added in v0.11.0
RecoveryPage renders the recovery login page.
func (*App) RegenerateRecoveryCodes ¶ added in v0.11.0
RegenerateRecoveryCodes generates new recovery codes and invalidates old ones.
func (*App) RegisterBegin ¶ added in v0.11.0
RegisterBegin starts the WebAuthn registration process.
func (*App) RegisterFinish ¶ added in v0.11.0
RegisterFinish completes the WebAuthn registration process.
func (*App) RegisterJobs ¶
RegisterJobs registers auth email job handlers with the queue. Skipped when no email service is configured (WithEmailService was not called), since there is nothing to deliver.
func (*App) RegisterPage ¶ added in v0.11.0
RegisterPage renders the registration page.
func (*App) Repo ¶
func (a *App) Repo() *Repository
Repo returns the auth repository for external access.
func (*App) RequestFuncMap ¶
RequestFuncMap returns request-scoped template functions for auth state.
func (*App) RequireAdmin ¶ added in v0.13.0
RequireAdmin satisfies the burrow.AdminAuth interface.
func (*App) RequireAuth ¶ added in v0.13.0
RequireAuth satisfies the burrow.AdminAuth interface so the admin app can discover auth middleware from the registry without importing this package.
func (*App) ResendVerification ¶ added in v0.11.0
ResendVerification resends the verification email.
func (*App) Shutdown ¶
Shutdown stops the background cleanup goroutine. Safe to call multiple times or if Configure was never called.
func (*App) Start ¶ added in v0.10.0
Start launches the background cleanup goroutine after the full boot sequence completes. This ensures the goroutine only runs when the server has started successfully.
func (*App) StaticFS ¶
StaticFS returns the embedded static assets (webauthn.js) under the "auth" prefix.
func (*App) TemplateFS ¶
TemplateFS returns the embedded HTML template files.
func (*App) TranslationFS ¶
TranslationFS returns the embedded translation files for auto-discovery by the i18n app.
func (*App) UseEmailMode ¶ added in v0.11.0
UseEmailMode returns true if email-based authentication is enabled.
func (*App) VerifyEmail ¶ added in v0.11.0
VerifyEmail handles the email verification link.
func (*App) VerifyPendingPage ¶ added in v0.11.0
VerifyPendingPage renders the "check your email" page.
type Config ¶
type Config struct {
LoginRedirect string
LogoutRedirect string
BaseURL string
UseEmail bool
RequireVerification bool
InviteOnly bool
}
Config holds auth-specific configuration.
type CreateInviteRequest ¶
CreateInviteRequest is the request body for creating an invite.
type Credential ¶
type Credential struct {
document.Base
CredentialID []byte `json:"credential_id" den:"unique"`
PublicKey []byte `json:"public_key"`
AAGUID []byte `json:"aaguid"`
AttestationType string `json:"attestation_type"`
Transports string `json:"transports"`
Name string `json:"name"`
UserID string `json:"user_id" den:"index"`
SignCount uint32 `json:"sign_count"`
BackupState bool `json:"backup_state"`
BackupEligible bool `json:"backup_eligible"`
}
Credential stores a WebAuthn credential for a user.
func NewCredentialFromWebAuthn ¶
func NewCredentialFromWebAuthn(userID string, cred *webauthn.Credential) *Credential
NewCredentialFromWebAuthn creates a Credential from a WebAuthn registration result.
func (*Credential) ToWebAuthn ¶
func (c *Credential) ToWebAuthn() webauthn.Credential
ToWebAuthn converts the stored credential to the WebAuthn library type.
type EmailService ¶
type EmailService interface {
SendVerification(ctx context.Context, toEmail, verifyURL string) error
SendInvite(ctx context.Context, toEmail, inviteURL string) error
}
EmailService defines email operations.
type EmailVerificationToken ¶
type EmailVerificationToken struct {
document.Base
ExpiresAt time.Time `json:"expires_at"`
TokenHash string `json:"token_hash" den:"unique"`
UserID string `json:"user_id" den:"index"`
}
EmailVerificationToken stores a hashed token for email verification.
type Invite ¶
type Invite struct {
document.Base
ExpiresAt time.Time `json:"expires_at" form:"-" verbose:"Expires at"`
UsedAt *time.Time `json:"used_at,omitempty" form:"-"`
UsedBy *string `json:"used_by,omitempty" form:"-"`
CreatedBy *string `json:"created_by,omitempty" form:"-"`
Email string `json:"email" verbose:"Email"`
Label string `json:"label" verbose:"Label"`
TokenHash string `json:"token_hash" den:"unique" form:"-"`
}
Invite represents an invitation to register.
type Option ¶
type Option func(*App)
Option configures the auth app.
func WithAuthLayout ¶
WithAuthLayout sets an optional layout template name for public (unauthenticated) auth pages. When set, pages like login, register, and recovery use this layout instead of the global app layout. Authenticated routes (credentials, recovery codes) continue to use the global layout.
func WithEmailService ¶
func WithEmailService(e EmailService) Option
WithEmailService sets the email service for the auth app.
func WithLogoComponent ¶
WithLogoComponent sets an optional logo HTML rendered above auth page content. When set, the logo appears on login, register, and recovery pages.
func WithRenderer ¶
WithRenderer sets the page renderer for auth views.
type RecoveryCode ¶
type RecoveryCode struct {
document.Base
UsedAt *time.Time `json:"used_at,omitempty"`
CodeHash string `json:"code_hash"`
UserID string `json:"user_id" den:"index,index_together:recovery_status"`
Used bool `json:"used" den:"index_together:recovery_status"`
}
RecoveryCode stores a hashed recovery code for account recovery.
type RecoveryLoginRequest ¶
type RecoveryLoginRequest struct {
Username string `json:"username" form:"username"`
Code string `json:"code" form:"code"`
}
RecoveryLoginRequest is the request body for recovery login.
type RecoveryService ¶
type RecoveryService struct {
// BcryptCost overrides the default bcrypt cost. Use bcrypt.MinCost in tests.
BcryptCost int
}
RecoveryService handles recovery code generation.
func NewRecoveryService ¶
func NewRecoveryService() *RecoveryService
NewRecoveryService creates a new recovery service.
func (*RecoveryService) GenerateCodes ¶
func (s *RecoveryService) GenerateCodes(count int) ([]string, []string, error)
GenerateCodes generates recovery codes and their bcrypt hashes. Returns (plaintext codes for display, hashed codes for storage, error).
type RegisterBeginRequest ¶
type RegisterBeginRequest struct {
Username string `json:"username"`
Email string `json:"email"`
Name string `json:"name"`
Invite string `json:"invite"`
}
RegisterBeginRequest is the request body for starting registration.
type Renderer ¶
type Renderer interface {
RegisterPage(w http.ResponseWriter, r *http.Request, useEmail, inviteOnly bool, email, invite string) error
LoginPage(w http.ResponseWriter, r *http.Request, loginRedirect string) error
CredentialsPage(w http.ResponseWriter, r *http.Request, creds []Credential) error
RecoveryPage(w http.ResponseWriter, r *http.Request, loginRedirect string) error
RecoveryCodesPage(w http.ResponseWriter, r *http.Request, codes []string) error
VerifyPendingPage(w http.ResponseWriter, r *http.Request) error
VerifyEmailSuccessPage(w http.ResponseWriter, r *http.Request) error
VerifyEmailErrorPage(w http.ResponseWriter, r *http.Request, errorCode string) error
}
Renderer defines the page rendering interface for auth templates. Projects implement this to provide their own template rendering.
func DefaultRenderer ¶
func DefaultRenderer() Renderer
DefaultRenderer returns the default Renderer that uses the built-in HTML templates. Templates use burrow.RenderTemplate which reads layout from context: if a layout is set, page content is wrapped in it; otherwise bare content is rendered.
type Repository ¶
type Repository struct {
// contains filtered or unexported fields
}
Repository provides data access for auth models.
func NewRepository ¶
func NewRepository(db *den.DB) *Repository
NewRepository creates a new auth Repository.
func (*Repository) CountAdminUsers ¶
func (r *Repository) CountAdminUsers(ctx context.Context) (int, error)
CountAdminUsers returns the number of users with the admin role.
func (*Repository) CountUserCredentials ¶
CountUserCredentials counts the number of credentials for a user.
func (*Repository) CountUsers ¶
func (r *Repository) CountUsers(ctx context.Context) (int, error)
CountUsers returns the total number of users.
func (*Repository) CreateCredential ¶
func (r *Repository) CreateCredential(ctx context.Context, cred *Credential) error
CreateCredential creates a new WebAuthn credential.
func (*Repository) CreateEmailVerificationToken ¶
func (r *Repository) CreateEmailVerificationToken(ctx context.Context, userID string, tokenHash string, expiresAt time.Time) error
CreateEmailVerificationToken creates a new email verification token.
func (*Repository) CreateInvite ¶
func (r *Repository) CreateInvite(ctx context.Context, invite *Invite) error
CreateInvite creates a new invite record.
func (*Repository) CreateRecoveryCodes ¶
func (r *Repository) CreateRecoveryCodes(ctx context.Context, userID string, codeHashes []string) error
CreateRecoveryCodes creates recovery codes for a user.
func (*Repository) CreateUser ¶
CreateUser creates a new user with a username and optional name.
func (*Repository) CreateUserWithEmail ¶
CreateUserWithEmail creates a new user with email and optional name.
func (*Repository) DeleteCredential ¶
func (r *Repository) DeleteCredential(ctx context.Context, credID, userID string) error
DeleteCredential deletes a credential.
func (*Repository) DeleteEmailVerificationToken ¶
func (r *Repository) DeleteEmailVerificationToken(ctx context.Context, tokenID string) error
DeleteEmailVerificationToken deletes a token.
func (*Repository) DeleteExpiredEmailVerificationTokens ¶
func (r *Repository) DeleteExpiredEmailVerificationTokens(ctx context.Context) error
DeleteExpiredEmailVerificationTokens deletes expired tokens.
func (*Repository) DeleteInvite ¶
func (r *Repository) DeleteInvite(ctx context.Context, inviteID string) error
DeleteInvite deletes an invite (revoke).
func (*Repository) DeleteRecoveryCodes ¶
func (r *Repository) DeleteRecoveryCodes(ctx context.Context, userID string) error
DeleteRecoveryCodes deletes all recovery codes for a user.
func (*Repository) DeleteUser ¶
func (r *Repository) DeleteUser(ctx context.Context, id string) error
DeleteUser permanently deletes a user by ID.
func (*Repository) DeleteUserEmailVerificationTokens ¶
func (r *Repository) DeleteUserEmailVerificationTokens(ctx context.Context, userID string) error
DeleteUserEmailVerificationTokens deletes all tokens for a user.
func (*Repository) EmailExists ¶
EmailExists checks if a user with the given email exists.
func (*Repository) GetCredentialsByUserID ¶
func (r *Repository) GetCredentialsByUserID(ctx context.Context, userID string) ([]Credential, error)
GetCredentialsByUserID retrieves all credentials for a user.
func (*Repository) GetEmailVerificationToken ¶
func (r *Repository) GetEmailVerificationToken(ctx context.Context, tokenHash string) (*EmailVerificationToken, error)
GetEmailVerificationToken retrieves a token by hash.
func (*Repository) GetInviteByID ¶ added in v0.13.0
GetInviteByID retrieves an invite by its ID.
func (*Repository) GetInviteByTokenHash ¶
GetInviteByTokenHash retrieves an invite by its token hash.
func (*Repository) GetUnusedRecoveryCodeCount ¶
GetUnusedRecoveryCodeCount returns the count of unused recovery codes.
func (*Repository) GetUnusedRecoveryCodes ¶
func (r *Repository) GetUnusedRecoveryCodes(ctx context.Context, userID string) ([]RecoveryCode, error)
GetUnusedRecoveryCodes retrieves unused recovery codes for a user.
func (*Repository) GetUserByEmail ¶
GetUserByEmail retrieves a user by email.
func (*Repository) GetUserByID ¶
GetUserByID retrieves a user by ID.
func (*Repository) GetUserByIDWithCredentials ¶
GetUserByIDWithCredentials retrieves a user by ID with preloaded credentials.
func (*Repository) GetUserByUsername ¶
GetUserByUsername retrieves a user by username.
func (*Repository) HasRecoveryCodes ¶
HasRecoveryCodes checks if a user has any recovery codes.
func (*Repository) ListInvites ¶
func (r *Repository) ListInvites(ctx context.Context) ([]Invite, error)
ListInvites returns all invites ordered by creation date descending.
func (*Repository) ListInvitesPaged ¶ added in v0.13.0
func (r *Repository) ListInvitesPaged(ctx context.Context, pr burrow.PageRequest) ([]Invite, burrow.PageResult, error)
ListInvitesPaged returns invites with pagination, ordered by created_at desc.
func (*Repository) ListUsers ¶
func (r *Repository) ListUsers(ctx context.Context) ([]User, error)
ListUsers returns all users ordered by creation time ascending.
func (*Repository) ListUsersPaged ¶ added in v0.13.0
func (r *Repository) ListUsersPaged(ctx context.Context, pr burrow.PageRequest, role string) ([]User, burrow.PageResult, error)
ListUsersPaged returns users with pagination and optional role filter, ordered by created_at desc.
func (*Repository) MarkEmailVerified ¶
func (r *Repository) MarkEmailVerified(ctx context.Context, userID string) error
MarkEmailVerified marks a user's email as verified.
func (*Repository) MarkInviteUsed ¶
func (r *Repository) MarkInviteUsed(ctx context.Context, inviteID, userID string) error
MarkInviteUsed atomically marks an invite as used by the given user. The condition used_at IS NULL ensures only the first caller succeeds, preventing a race condition where two registrations consume the same invite.
func (*Repository) MarkRecoveryCodeUsed ¶
func (r *Repository) MarkRecoveryCodeUsed(ctx context.Context, codeID string) error
MarkRecoveryCodeUsed marks a recovery code as used.
func (*Repository) PurgeOrphanedUsers ¶
PurgeOrphanedUsers deletes users with zero credentials that were created more than the given duration ago. These are leftover from abandoned WebAuthn registration flows where the client never called RegisterFinish.
func (*Repository) SearchInvitesPaged ¶ added in v0.18.0
func (r *Repository) SearchInvitesPaged(ctx context.Context, query string, pr burrow.PageRequest) ([]Invite, burrow.PageResult, error)
SearchInvitesPaged searches invites by label or email with pagination, ordered by created_at desc.
func (*Repository) SearchUsers ¶ added in v0.13.0
func (r *Repository) SearchUsers(ctx context.Context, query string, pr burrow.PageRequest, role string) ([]User, burrow.PageResult, error)
SearchUsers searches users by username, name, or email with pagination and optional role filter.
func (*Repository) SetUserActive ¶
SetUserActive sets a user's is_active flag.
func (*Repository) SetUserRole ¶
SetUserRole updates a user's role.
func (*Repository) UpdateCredentialSignCount ¶
func (r *Repository) UpdateCredentialSignCount(ctx context.Context, credentialID []byte, signCount uint32) error
UpdateCredentialSignCount updates the sign count for a credential.
func (*Repository) UpdateUser ¶
func (r *Repository) UpdateUser(ctx context.Context, user *User) error
UpdateUser updates a user record.
func (*Repository) UserExists ¶
UserExists checks if a user with the given username exists.
func (*Repository) ValidateAndUseRecoveryCode ¶
func (r *Repository) ValidateAndUseRecoveryCode(ctx context.Context, userID string, code string) (bool, error)
ValidateAndUseRecoveryCode validates and marks a recovery code as used. It always iterates all codes to prevent timing attacks that could reveal which code position matched.
type ResendVerificationRequest ¶
type ResendVerificationRequest struct {
Email string `json:"email" form:"email"`
}
ResendVerificationRequest is the request body for resending verification email.
type User ¶
type User struct {
document.Base
EmailVerifiedAt *time.Time `json:"email_verified_at,omitempty" form:"-"`
Email *string `json:"email,omitempty" den:"unique" form:"email" verbose:"Email"`
Name string `json:"name,omitempty" form:"name" verbose:"Name"`
Bio string `json:"bio,omitempty" form:"bio" verbose:"Bio"`
Role string `json:"role" den:"index" form:"role" verbose:"Role"`
Username string `json:"username" den:"unique" form:"username" verbose:"Username"`
Credentials []Credential `json:"credentials,omitempty" form:"-"` // populated by separate query, not embedded
EmailVerified bool `json:"email_verified" form:"-"`
IsActive bool `json:"is_active" form:"is_active" verbose:"Active"`
}
User represents an authenticated user with WebAuthn credentials.
func CurrentUser ¶ added in v0.6.0
CurrentUser retrieves the authenticated user from the context.
Example ¶
package main
import (
"context"
"fmt"
"github.com/oliverandrich/burrow/contrib/auth"
)
func main() {
user := &auth.User{Username: "alice", Role: "admin"}
ctx := auth.WithUser(context.Background(), user)
u := auth.CurrentUser(ctx)
fmt.Println(u.Username, u.Role)
}
Output: alice admin
func MustCurrentUser ¶ added in v0.9.0
MustCurrentUser returns the authenticated user from the context. It panics if no user is present — only use in handlers protected by RequireAuth middleware.
func UserFromContext ¶
UserFromContext is a deprecated alias for CurrentUser.
func (User) String ¶ added in v0.5.0
String returns the user's display name (Name if set, otherwise Username).
func (*User) WebAuthnCredentials ¶
func (u *User) WebAuthnCredentials() []webauthn.Credential
WebAuthnCredentials returns the user's WebAuthn credentials.
func (*User) WebAuthnDisplayName ¶
WebAuthnDisplayName returns the display name or falls back to username.
func (*User) WebAuthnID ¶
WebAuthnID returns the user ID as bytes for the WebAuthn protocol. The ULID string is unique and stable, so we use it directly.
func (*User) WebAuthnIcon ¶
WebAuthnIcon returns an empty string (deprecated by the spec).
type WebAuthnService ¶
type WebAuthnService interface {
WebAuthn() *gowebauthn.WebAuthn
StoreRegistrationSession(userID string, data *gowebauthn.SessionData)
GetRegistrationSession(userID string) (*gowebauthn.SessionData, error)
StoreDiscoverableSession(sessionID string, data *gowebauthn.SessionData)
GetDiscoverableSession(sessionID string) (*gowebauthn.SessionData, error)
}
WebAuthnService defines WebAuthn operations.
func NewWebAuthnService ¶
func NewWebAuthnService(ctx context.Context, rpDisplayName, rpID, rpOrigin string) (WebAuthnService, error)
NewWebAuthnService creates a new WebAuthn service with the given RP configuration. The context controls the lifetime of the background cleanup goroutine.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
Package authtest provides test helpers for creating auth-migrated databases and test users, following the convention of net/http/httptest.
|
Package authtest provides test helpers for creating auth-migrated databases and test users, following the convention of net/http/httptest. |