core

package
v0.4.5 Latest Latest
Warning

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

Go to latest
Published: Feb 4, 2026 License: MIT Imports: 24 Imported by: 0

Documentation

Index

Constants

View Source
const SolanaProviderSlug = "solana"

SolanaProviderSlug is the provider slug used for Solana wallets.

Variables

View Source
var (
	// ErrUserBanned indicates the account is blocked from authenticating.
	ErrUserBanned = errors.New("user_banned")
	// ErrUserNotFound indicates a user does not exist (or is not visible).
	ErrUserNotFound = errors.New("user_not_found")
)
View Source
var (
	ErrOrgNotFound      = errors.New("org_not_found")
	ErrNotOrgMember     = errors.New("not_org_member")
	ErrInvalidOrgSlug   = errors.New("invalid_org_slug")
	ErrInvalidOrgRole   = errors.New("invalid_org_role")
	ErrProtectedOrgRole = errors.New("protected_org_role")
	ErrLastOrgOwner     = errors.New("cannot_remove_last_owner")
)
View Source
var ErrReservedRoleSlug = errors.New("reserved_role_slug")

Functions

func IsDevEnvironment

func IsDevEnvironment() bool

IsDevEnvironment reports whether the current ENV/APP_ENV/ENVIRONMENT is non-production.

func WithSessionRevokeReason

func WithSessionRevokeReason(ctx context.Context, reason SessionRevokeReason) context.Context

WithSessionRevokeReason annotates ctx so revoke paths can emit a structured reason to the auth logger.

Types

type AcceptConfig

type AcceptConfig struct {
	Issuers    []IssuerAccept
	Skew       time.Duration
	Algorithms []string
}

AcceptConfig configures verification of third-party JWTs (verify-only mode).

type AdminListUsersResult

type AdminListUsersResult struct {
	Users  []AdminUser `json:"users"`
	Total  int64       `json:"total"`
	Limit  int         `json:"limit"`
	Offset int         `json:"offset"`
}

AdminListUsersResult contains paginated user list with total count

type AdminUser

type AdminUser struct {
	ID              string     `json:"id"`
	Email           *string    `json:"email"` // Nullable for phone-only users
	PhoneNumber     *string    `json:"phone_number"`
	Username        *string    `json:"username"`
	DiscordUsername *string    `json:"discord_username"`
	EmailVerified   bool       `json:"email_verified"`
	PhoneVerified   bool       `json:"phone_verified"`
	BannedAt        *time.Time `json:"banned_at,omitempty"`
	BannedUntil     *time.Time `json:"banned_until,omitempty"`
	BanReason       *string    `json:"ban_reason,omitempty"`
	BannedBy        *string    `json:"banned_by,omitempty"`
	DeletedAt       *time.Time `json:"deleted_at"`
	Biography       *string    `json:"biography"`
	CreatedAt       time.Time  `json:"created_at"`
	UpdatedAt       time.Time  `json:"updated_at"`
	LastLogin       *time.Time `json:"last_login"`
	Roles           []string   `json:"roles"`
	Entitlements    []string   `json:"entitlements"`
}

Admin listing/get/delete

type AuthEventLogReader added in v0.4.2

type AuthEventLogReader interface {
	// ListSessionEvents returns session events matching any of the given event types.
	// If userID is empty, returns events for all users.
	ListSessionEvents(ctx context.Context, userID string, eventTypes ...SessionEventType) ([]AuthSessionEvent, error)
}

AuthEventLogReader allows listing session events filtered by event types and optional userID.

type AuthEventLogger

type AuthEventLogger interface {
	LogSessionEvent(ctx context.Context, e AuthSessionEvent) error
}

type AuthSessionEvent

type AuthSessionEvent struct {
	OccurredAt time.Time
	Issuer     string
	UserID     string
	SessionID  string
	Event      SessionEventType
	Method     *string
	Reason     *string
	IPAddr     *string
	UserAgent  *string
}

AuthSessionEvent is a best-effort, append-only session lifecycle record intended for external sinks.

ClickHouse schema expectation (see migrations/clickhouse): - issuer, user_id, session_id, event are required - method is typically set for SessionEventCreated - reason is typically set for SessionEventRevoked

type Config

type Config struct {
	Issuer          string
	IssuedAudiences []string // JWT audiences - tokens issued will contain ALL of these audiences
	// ExpectedAudiences enforces that verified access tokens contain at least one
	// of these audiences. Prefer this over ExpectedAudience for new integrations.
	ExpectedAudiences []string
	// ExpectedAudience enforces a single required audience for verified access tokens.
	// Deprecated: prefer ExpectedAudiences.
	ExpectedAudience     string
	AccessTokenDuration  time.Duration
	RefreshTokenDuration time.Duration
	// Session limits
	SessionMaxPerUser int // 0 = unlimited, default 3 if unset by service; eviction is always evict-oldest
	// Optional: if set, used for building absolute URLs (e.g., password reset/verify links).
	BaseURL string

	// OrgMode controls multi-organization behavior.
	// Valid values: "single" (default) or "multi".
	OrgMode string

	// Keys can be nil - if nil, authkit auto-discovers keys with this priority:
	// 1. Environment variables (ACTIVE_KEY_ID, ACTIVE_PRIVATE_KEY_PEM, PUBLIC_KEYS)
	// 2. Filesystem /vault/auth/keys.json (External Secrets Operator in K8s)
	// 3. Auto-generated keys in .runtime/authkit/ (development fallback)
	Keys jwtkit.KeySource

	// Providers – identity providers by name ("google", "apple", "github", "discord").
	// Only client id/secret are required; standard scopes are derived from defaults.
	Providers map[string]oidckit.RPConfig
}

Config mirrors the simplicity of go-pkgz/auth: provide issuer, durations, and keys.

type EmailSender

type EmailSender interface {
	// SendPasswordResetCode sends a password reset code to the user's email with personalization.
	// AuthKit looks up the user's current email and username before calling this.
	SendPasswordResetCode(ctx context.Context, email, username, code string) error

	// SendEmailVerificationCode sends an email verification code to the given email address and username.
	// User doesn't exist yet, so email and username are provided directly for personalization.
	SendEmailVerificationCode(ctx context.Context, email, username, code string) error

	// SendLoginCode sends a two-factor authentication code to the user's email during login.
	// AuthKit looks up the user's email and username before calling this.
	SendLoginCode(ctx context.Context, email, username, code string) error

	// SendWelcome sends a welcome email to the user's email with personalization.
	// AuthKit looks up the user's email and username before calling this.
	SendWelcome(ctx context.Context, email, username string) error
}

EmailSender sends password reset emails.

type EmailSenderWithPasswordResetLink interface {
	SendPasswordResetLink(ctx context.Context, email, username, token string) error
}

EmailSenderWithPasswordResetLink is an optional extension interface for URL-based password reset.

AuthKit does NOT construct user-facing URLs (site base URL + route). Host apps own templates and should embed the provided token into their chosen reset URL.

type EntitlementsProvider

type EntitlementsProvider interface {
	ListEntitlements(ctx context.Context, userID string) ([]entpg.Entitlement, error)
}

EntitlementsProvider returns application entitlements for a user (e.g., billing tiers).

type EphemeralMode

type EphemeralMode string
const (
	EphemeralMemory EphemeralMode = "memory"
	EphemeralRedis  EphemeralMode = "redis"
)

type EphemeralStore

type EphemeralStore interface {
	Get(ctx context.Context, key string) ([]byte, bool, error)
	Set(ctx context.Context, key string, value []byte, ttl time.Duration) error
	Del(ctx context.Context, key string) error
}

EphemeralStore is a minimal key-value interface used for short-lived auth state. Implementations should honor TTL on Set and treat missing keys as (found=false, err=nil).

type IssuerAccept

type IssuerAccept struct {
	Issuer string
	// Audiences enforces that verified access tokens contain at least one of
	// these audiences. Prefer this over Audience for new integrations.
	Audiences []string
	// Audience enforces a single required audience for this issuer.
	// Deprecated: prefer Audiences.
	Audience     string
	JWKSURL      string
	PinnedRSAPEM string // optional PEM for degraded fallback
	CacheTTL     time.Duration
	MaxStale     time.Duration
}

IssuerAccept describes how to accept tokens from a specific issuer.

type Keyset

type Keyset struct {
	Active     jwtkit.Signer
	PublicKeys map[string]*rsa.PublicKey // kid -> pub
}

Keyset holds the active signer and the public keys exposed via JWKS.

type Options

type Options struct {
	Issuer          string
	IssuedAudiences []string // JWT audiences - tokens issued will contain ALL of these audiences
	// ExpectedAudiences enforces that verified access tokens contain at least one
	// of these audiences. Prefer this over ExpectedAudience for new integrations.
	ExpectedAudiences []string
	// ExpectedAudience enforces a single required audience for verified access tokens.
	// Deprecated: prefer ExpectedAudiences.
	ExpectedAudience     string
	AccessTokenDuration  time.Duration
	RefreshTokenDuration time.Duration
	SessionMaxPerUser    int
	// Optional link building (paths are fixed: /reset and /verify)
	BaseURL string

	// OrgMode controls multi-organization behavior.
	// Valid values: "single" or "multi".
	OrgMode string
}

Options configures issued tokens and identifiers.

type Org added in v0.4.4

type Org struct {
	ID   string
	Slug string
}

Org is a minimal org record.

type OrgMembership added in v0.4.4

type OrgMembership struct {
	Org   string
	Roles []string
}

OrgMembership is a user's membership with optional roles.

type PendingRegistration

type PendingRegistration struct {
	Email        string
	Username     string
	PasswordHash string
}

PendingRegistration represents an unverified registration

type Provider

type Provider interface {
	// 2FA phone setup
	SendPhone2FASetupCode(ctx context.Context, userID, phone, code string) error
	VerifyPhone2FASetupCode(ctx context.Context, userID, phone, code string) (bool, error)
	Verifier
	RequestPhoneChange(ctx context.Context, userID, newPhone string) error
	ConfirmPhoneChange(ctx context.Context, userID, phone, code string) error
	ResendPhoneChangeCode(ctx context.Context, userID, phone string) error

	// Token/session minting
	IssueAccessToken(ctx context.Context, userID, email string, extra map[string]any) (token string, expiresAt time.Time, err error)
	IssueRefreshSession(ctx context.Context, userID, userAgent string, ip net.IP) (sessionID, refreshToken string, expiresAt *time.Time, err error)
	ExchangeRefreshToken(ctx context.Context, refreshToken string, ua string, ip net.IP) (idToken string, expiresAt time.Time, newRefresh string, err error)
	ResolveSessionByRefresh(ctx context.Context, refreshToken string) (string, error)

	// Session management (self-service)
	ListUserSessions(ctx context.Context, userID string) ([]Session, error)
	RevokeSessionByIDForUser(ctx context.Context, userID, sessionID string) error
	RevokeAllSessions(ctx context.Context, userID string, keepSessionID *string) error
	SoftDeleteUser(ctx context.Context, userID string) error
	BanUser(ctx context.Context, userID string, reason *string, until *time.Time, bannedBy string) error
	UnbanUser(ctx context.Context, userID string) error

	// Password + registration
	PasswordLogin(ctx context.Context, email, pass string, extra map[string]any) (string, time.Time, error)
	PasswordLoginByUserID(ctx context.Context, userID, pass string, extra map[string]any) (string, time.Time, error)
	ChangePassword(ctx context.Context, userID, current, new string, keepSessionID *string) error
	// AdminSetPassword force-sets a user's password (admin only, no current password required)
	AdminSetPassword(ctx context.Context, userID, new string) error
	HasPassword(ctx context.Context, userID string) bool

	HasEmailSender() bool
	HasSMSSender() bool

	RequestPasswordReset(ctx context.Context, email string, ttl time.Duration) error
	ConfirmPasswordReset(ctx context.Context, token string, newPassword string) (string, error)
	RequestPhonePasswordReset(ctx context.Context, phone string, ttl time.Duration) error
	ConfirmPhonePasswordReset(ctx context.Context, phone, code, newPassword string) (string, error)

	// Email verification
	RequestEmailVerification(ctx context.Context, email string, ttl time.Duration) error
	ConfirmEmailVerification(ctx context.Context, tokenHash string) (string, error)

	// Pending registrations
	GetPendingRegistrationByEmail(ctx context.Context, email string) (*PendingRegistration, error)
	GetPendingPhoneRegistrationByPhone(ctx context.Context, phone string) (*PendingRegistration, error)
	VerifyPendingPassword(ctx context.Context, email, pass string) bool
	CheckPendingRegistrationConflict(ctx context.Context, email, username string) (emailTaken, usernameTaken bool, err error)
	CreatePendingRegistration(ctx context.Context, email, username, passwordHash string, ttl time.Duration) (string, error)
	CheckPhoneRegistrationConflict(ctx context.Context, phone, username string) (phoneTaken, usernameTaken bool, err error)
	CreatePendingPhoneRegistration(ctx context.Context, phone, username, passwordHash string) (string, error)
	ConfirmPendingRegistration(ctx context.Context, token string) (string, error)
	ConfirmPendingPhoneRegistration(ctx context.Context, phone, code string) (string, error)

	// Phone verification (existing users)
	RequestPhoneVerification(ctx context.Context, phone string, ttl time.Duration) error
	SendPhoneVerificationToUser(ctx context.Context, phone, userID string, ttl time.Duration) error

	// Identity lookup/provisioning
	GetUserByEmail(ctx context.Context, email string) (*User, error)
	GetUserByUsername(ctx context.Context, username string) (*User, error)
	GetUserByPhone(ctx context.Context, phone string) (*User, error)
	CreateUser(ctx context.Context, email, username string) (*User, error)
	SetEmailVerified(ctx context.Context, id string, v bool) error
	UpdateUsername(ctx context.Context, id, username string) error
	UpdateEmail(ctx context.Context, id, email string) error
	UpdateBiography(ctx context.Context, id string, bio *string) error

	// OIDC/provider links
	GetProviderLink(ctx context.Context, providerSlug, subject string) (string, *string, error)
	GetProviderLinkByIssuer(ctx context.Context, issuer, subject string) (string, *string, error)
	LinkProviderByIssuer(ctx context.Context, userID, issuer, providerSlug, subject string, email *string) error
	SetProviderUsername(ctx context.Context, userID, provider, subject, username string) error
	DeriveUsernameForOAuth(ctx context.Context, provider, preferred, email, displayName string) string

	// Email change
	RequestEmailChange(ctx context.Context, userID, newEmail string) error
	ConfirmEmailChange(ctx context.Context, userID, code string) error
	ResendEmailChangeCode(ctx context.Context, userID string) error

	// 2FA
	Get2FASettings(ctx context.Context, userID string) (*TwoFactorSettings, error)
	Enable2FA(ctx context.Context, userID, method string, phoneNumber *string) ([]string, error)
	Disable2FA(ctx context.Context, userID string) error
	Verify2FACode(ctx context.Context, userID, code string) (bool, error)
	VerifyBackupCode(ctx context.Context, userID, code string) (bool, error)
	RegenerateBackupCodes(ctx context.Context, userID string) ([]string, error)
	Require2FAForLogin(ctx context.Context, userID string) (string, error)
	Create2FAChallenge(ctx context.Context, userID string) (string, error)
	Verify2FAChallenge(ctx context.Context, userID, challenge string) (bool, error)
	Clear2FAChallenge(ctx context.Context, userID string) error

	// Solana SIWS
	GenerateSIWSChallenge(ctx context.Context, cache siws.ChallengeCache, domain, address, username string) (siws.SignInInput, error)
	VerifySIWSAndLogin(ctx context.Context, cache siws.ChallengeCache, output siws.SignInOutput, extra map[string]any) (accessToken string, expiresAt time.Time, refreshToken, userID string, created bool, err error)
	LinkSolanaWallet(ctx context.Context, cache siws.ChallengeCache, userID string, output siws.SignInOutput) error

	// Admin operations
	AdminListUsers(ctx context.Context, page, pageSize int, filter, search string, onlyDeleted bool) (*AdminListUsersResult, error)
	AdminGetUser(ctx context.Context, userID string) (*AdminUser, error)
	AdminDeleteUser(ctx context.Context, userID string) error
	HostDeleteUser(ctx context.Context, id string, soft bool) error
	RestoreUser(ctx context.Context, userID string) error
	AssignRoleBySlug(ctx context.Context, userID, slug string) error
	RemoveRoleBySlug(ctx context.Context, userID, slug string) error
	AdminListUserSessions(ctx context.Context, userID string) ([]Session, error)
	AdminRevokeUserSessions(ctx context.Context, userID string) error
	RevokeSessionByID(ctx context.Context, sessionID string) error

	// Link management
	CountProviderLinks(ctx context.Context, userID string) int
	UnlinkProvider(ctx context.Context, userID, provider string) error

	// Observability hooks
	LogSessionCreated(ctx context.Context, userID string, method string, sessionID string, ip *string, ua *string)
	SendWelcome(ctx context.Context, userID string)
}

Provider is the full auth surface needed by the built-in HTTP handlers. It is implemented by *Service and is intended as the template-friendly integration boundary for applications.

type SMSSender

type SMSSender interface {
	SendVerificationCode(ctx context.Context, phone, code string) error
	SendLoginCode(ctx context.Context, phone, code string) error
}

SMSSender sends verification and 2FA codes via SMS.

type SMSSenderWithPasswordResetLink interface {
	SendPasswordResetLink(ctx context.Context, phone, token string) error
}

SMSSenderWithPasswordResetLink is an optional extension interface for URL-based password reset via SMS.

This is separate from Twilio Verify (OTP/codes). Password reset links should be delivered via a messaging provider (e.g. Twilio Messaging/SMS API), not Verify.

type Service

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

Service is the core auth service used by HTTP adapters.

func NewFromConfig

func NewFromConfig(cfg Config) (*Service, error)

NewFromConfig creates a Service from high-level Config + Stores. If Keys is nil, auto-discovers keys from environment variables, filesystem, or generates development keys.

func NewService

func NewService(opts Options, keys Keyset) *Service

func (*Service) AddMember added in v0.4.4

func (s *Service) AddMember(ctx context.Context, orgSlug, userID string) error

func (*Service) AdminDeleteUser

func (s *Service) AdminDeleteUser(ctx context.Context, id string) error

func (*Service) AdminGetUser

func (s *Service) AdminGetUser(ctx context.Context, id string) (*AdminUser, error)

func (*Service) AdminListUserSessions

func (s *Service) AdminListUserSessions(ctx context.Context, userID string) ([]Session, error)

Helper exposed for admin endpoints

func (*Service) AdminListUsers

func (s *Service) AdminListUsers(ctx context.Context, page, pageSize int, filter, search string, onlyDeleted bool) (*AdminListUsersResult, error)

func (*Service) AdminRevokeUserSessions

func (s *Service) AdminRevokeUserSessions(ctx context.Context, userID string) error

func (*Service) AdminSetPassword

func (s *Service) AdminSetPassword(ctx context.Context, userID, new string) error

AdminSetPassword force-sets a user's password (admin only, no current password required)

func (*Service) AssignRole added in v0.4.4

func (s *Service) AssignRole(ctx context.Context, orgSlug, userID, role string) error

func (*Service) AssignRoleBySlug

func (s *Service) AssignRoleBySlug(ctx context.Context, userID, slug string) error

Exported wrappers for admin endpoints

func (*Service) BanUser

func (s *Service) BanUser(ctx context.Context, userID string, reason *string, until *time.Time, bannedBy string) error

BanUser disables a user account and stores ban metadata.

func (*Service) ChangePassword

func (s *Service) ChangePassword(ctx context.Context, userID, current, new string, keepSessionID *string) error

ChangePassword sets or changes a user's password. If the user already has a password, current must verify; otherwise current is ignored. Always Argon2id-hashes the new password and upserts it, then revokes all other sessions for the user; caller may keep one active session via keepSessionID.

func (*Service) CheckPendingRegistrationConflict

func (s *Service) CheckPendingRegistrationConflict(ctx context.Context, email, username string) (bool, bool, error)

CheckPendingRegistrationConflict checks if email or username exists in users or pending registration cache. Returns (emailTaken, usernameTaken, error)

func (*Service) CheckPhoneRegistrationConflict

func (s *Service) CheckPhoneRegistrationConflict(ctx context.Context, phone, username string) (bool, bool, error)

CheckPhoneRegistrationConflict checks if phone or username exists in users OR pending tables. Returns (phoneTaken, usernameTaken, error)

func (*Service) Clear2FAChallenge

func (s *Service) Clear2FAChallenge(ctx context.Context, userID string) error

Clear2FAChallenge removes the stored challenge after successful 2FA verification.

func (*Service) ConfirmEmailChange

func (s *Service) ConfirmEmailChange(ctx context.Context, userID, code string) error

ConfirmEmailChange verifies the code and updates the user's email address. This is called when the user enters the verification code sent to their new email.

func (*Service) ConfirmEmailVerification

func (s *Service) ConfirmEmailVerification(ctx context.Context, token string) (userID string, err error)

ConfirmEmailVerification verifies a token and marks email_verified = true. Returns the userID of the verified user.

func (*Service) ConfirmPasswordReset

func (s *Service) ConfirmPasswordReset(ctx context.Context, token, newPassword string) (string, error)

ConfirmPasswordReset verifies token and sets a new password.

func (*Service) ConfirmPendingPhoneRegistration

func (s *Service) ConfirmPendingPhoneRegistration(ctx context.Context, phone, code string) (userID string, err error)

ConfirmPendingPhoneRegistration verifies code and creates the actual user account. Implements "first to verify wins" - whoever verifies first gets the username/phone.

func (*Service) ConfirmPendingRegistration

func (s *Service) ConfirmPendingRegistration(ctx context.Context, token string) (userID string, err error)

ConfirmPendingRegistration verifies token and creates the actual user account. This implements "first to verify wins" - whoever verifies first gets the username/email.

func (*Service) ConfirmPhoneChange

func (s *Service) ConfirmPhoneChange(ctx context.Context, userID, phone, code string) error

ConfirmPhoneChange verifies the code and updates the user's phone number. This is called when the user enters the verification code sent to their new phone.

func (*Service) ConfirmPhonePasswordReset

func (s *Service) ConfirmPhonePasswordReset(ctx context.Context, phone, code, newPassword string) (string, error)

ConfirmPhonePasswordReset verifies the code and sets a new password.

func (*Service) ConfirmPhoneVerification

func (s *Service) ConfirmPhoneVerification(ctx context.Context, phone, code string) error

ConfirmPhoneVerification verifies a token and marks phone_verified = true.

func (s *Service) CountProviderLinks(ctx context.Context, userID string) int

Public wrappers

func (*Service) Create2FAChallenge

func (s *Service) Create2FAChallenge(ctx context.Context, userID string) (string, error)

Create2FAChallenge creates a short-lived challenge to prove password verification before 2FA.

func (*Service) CreateOrg added in v0.4.4

func (s *Service) CreateOrg(ctx context.Context, slug string) (*Org, error)

func (*Service) CreatePendingPhoneRegistration

func (s *Service) CreatePendingPhoneRegistration(ctx context.Context, phone, username, passwordHash string) (string, error)

CreatePendingPhoneRegistration creates a pending phone registration and sends SMS verification code. Returns 6-digit code for verification. Code expires in 10 minutes (shorter than email).

func (*Service) CreatePendingRegistration

func (s *Service) CreatePendingRegistration(ctx context.Context, email, username, passwordHash string, ttl time.Duration) (string, error)

CreatePendingRegistration creates a pending registration and sends verification email. Returns token for verification. Allows duplicate pending registrations (last one wins).

func (*Service) CreateUser

func (s *Service) CreateUser(ctx context.Context, email, username string) (*User, error)

func (*Service) DefineRole added in v0.4.4

func (s *Service) DefineRole(ctx context.Context, orgSlug, role string) error

func (*Service) DeleteRole added in v0.4.4

func (s *Service) DeleteRole(ctx context.Context, orgSlug, role string) error

func (*Service) DeriveUsername

func (s *Service) DeriveUsername(email string) string

func (*Service) DeriveUsernameForOAuth

func (s *Service) DeriveUsernameForOAuth(ctx context.Context, provider, preferred, email, displayName string) string

DeriveUsernameForOAuth prefers provider-preferred usernames; falls back to email local part or display name.

func (*Service) Disable2FA

func (s *Service) Disable2FA(ctx context.Context, userID string) error

Disable2FA disables two-factor authentication for a user

func (*Service) Enable2FA

func (s *Service) Enable2FA(ctx context.Context, userID, method string, phoneNumber *string) ([]string, error)

Enable2FA enables two-factor authentication for a user and generates backup codes. Returns the plaintext backup codes (caller must show these to user ONCE).

func (*Service) EntitlementsProvider

func (s *Service) EntitlementsProvider() EntitlementsProvider

func (*Service) EphemeralMode

func (s *Service) EphemeralMode() EphemeralMode

func (*Service) ExchangeRefreshToken

func (s *Service) ExchangeRefreshToken(ctx context.Context, refreshToken string, ua string, ip net.IP) (idToken string, expiresAt time.Time, newRefresh string, err error)

ExchangeRefreshToken rotates a refresh token and returns a new ID token + refresh token.

func (*Service) ExchangeRefreshTokenWithOrg added in v0.4.5

func (s *Service) ExchangeRefreshTokenWithOrg(ctx context.Context, refreshToken string, ua string, ip net.IP, org string) (idToken string, expiresAt time.Time, newRefresh string, err error)

ExchangeRefreshTokenWithOrg rotates a refresh token and returns a new access token + refresh token. If org is provided and org_mode=multi, it mints an org-scoped access token (org + roles for that org).

func (*Service) GenerateAvailableUsername

func (s *Service) GenerateAvailableUsername(ctx context.Context, base string) string

GenerateAvailableUsername tries base, then minimal numeric suffixes, then a short fallback.

func (*Service) GenerateSIWSChallenge

func (s *Service) GenerateSIWSChallenge(ctx context.Context, cache siws.ChallengeCache, domain, address, username string) (siws.SignInInput, error)

GenerateSIWSChallenge creates a new SIWS challenge for the given address. The challenge is stored in the cache and must be verified within 15 minutes.

func (*Service) Get2FASettings

func (s *Service) Get2FASettings(ctx context.Context, userID string) (*TwoFactorSettings, error)

Get2FASettings retrieves a user's 2FA settings

func (*Service) GetDiscordUsername

func (s *Service) GetDiscordUsername(ctx context.Context, userID string) (string, error)

Convenience: Discord username

func (*Service) GetEmailByUserID

func (s *Service) GetEmailByUserID(ctx context.Context, id string) (string, error)

func (*Service) GetPendingEmailChange

func (s *Service) GetPendingEmailChange(ctx context.Context, userID string) (string, error)

GetPendingEmailChange retrieves the pending email change for a user, if any.

func (*Service) GetPendingPhoneRegistrationByPhone

func (s *Service) GetPendingPhoneRegistrationByPhone(ctx context.Context, phone string) (*PendingRegistration, error)

GetPendingPhoneRegistrationByPhone looks up a pending phone registration by phone number.

func (*Service) GetPendingRegistrationByEmail

func (s *Service) GetPendingRegistrationByEmail(ctx context.Context, email string) (*PendingRegistration, error)

GetPendingRegistrationByEmail looks up a pending registration by email.

func (s *Service) GetProviderLink(ctx context.Context, providerSlug, subject string) (string, *string, error)

Additional public helpers used by OIDC flow

func (*Service) GetProviderLinkByIssuer

func (s *Service) GetProviderLinkByIssuer(ctx context.Context, issuer, subject string) (string, *string, error)

Issuer-based provider link helpers (preferred)

func (*Service) GetProviderUsername

func (s *Service) GetProviderUsername(ctx context.Context, userID, provider string) (string, error)

func (*Service) GetSolanaAddress

func (s *Service) GetSolanaAddress(ctx context.Context, userID string) (string, error)

GetSolanaAddress retrieves the Solana wallet address linked to a user, if any.

func (*Service) GetUserByEmail

func (s *Service) GetUserByEmail(ctx context.Context, email string) (*User, error)

func (*Service) GetUserByPhone

func (s *Service) GetUserByPhone(ctx context.Context, phone string) (*User, error)

GetUserByPhone looks up a user by phone number.

func (*Service) GetUserBySolanaAddress

func (s *Service) GetUserBySolanaAddress(ctx context.Context, address string) (*User, error)

GetUserBySolanaAddress looks up a user by their Solana wallet address.

func (*Service) GetUserByUsername

func (s *Service) GetUserByUsername(ctx context.Context, username string) (*User, error)

func (*Service) HardDeleteUser

func (s *Service) HardDeleteUser(ctx context.Context, userID string) error

HardDeleteUser permanently deletes the user row and dependent AuthKit rows via ON DELETE CASCADE.

func (*Service) HasEmailSender

func (s *Service) HasEmailSender() bool

HasEmailSender returns true if an email sender is configured.

func (*Service) HasPassword

func (s *Service) HasPassword(ctx context.Context, userID string) bool

func (*Service) HasSMSSender

func (s *Service) HasSMSSender() bool

HasSMSSender returns true if an SMS sender is configured.

func (*Service) HostDeleteUser

func (s *Service) HostDeleteUser(ctx context.Context, id string, soft bool) error

HostDeleteUser performs deletion on behalf of the host application. If soft is true, it performs a soft delete (see SoftDeleteUser). If false, it hard-deletes the user and all dependent rows via ON DELETE CASCADE.

func (*Service) IsOrgMember added in v0.4.4

func (s *Service) IsOrgMember(ctx context.Context, orgSlug, userID string) (bool, error)

func (*Service) IsUserAllowed

func (s *Service) IsUserAllowed(ctx context.Context, userID string) (bool, error)

func (*Service) IssueAccessToken

func (s *Service) IssueAccessToken(ctx context.Context, userID, email string, extra map[string]any) (token string, expiresAt time.Time, err error)

IssueAccessToken builds and signs an access token (JWT) for the given user. Includes core registered claims plus: - roles (snapshot, org_mode=single only) - entitlements (snapshot) - email, username, discord_username (if available) Extra claims in `extra` are merged into the token body (e.g., sid).

func (*Service) IssueOrgAccessToken added in v0.4.4

func (s *Service) IssueOrgAccessToken(ctx context.Context, userID, email, orgSlug string, extra map[string]any) (token string, expiresAt time.Time, err error)

IssueOrgAccessToken builds and signs an org-scoped access token (JWT) for the given user. It is only valid in org_mode=multi, and only if the user is a member of the org. The token includes: - org (canonical slug) - roles (snapshot for that org)

func (*Service) IssueRefreshSession

func (s *Service) IssueRefreshSession(ctx context.Context, userID, userAgent string, ip net.IP) (sessionID, refreshToken string, expiresAt *time.Time, err error)

IssueRefreshSession creates a session row and returns a new refresh token string.

func (*Service) JWKS

func (s *Service) JWKS() jwtkit.JWKS

JWKS returns a JWKS built from configured public keys.

func (*Service) Keyfunc

func (s *Service) Keyfunc() func(token *jwt.Token) (any, error)

Keyfunc looks up a public key by KID, falling back to the active key if missing.

func (*Service) LinkProvider

func (s *Service) LinkProvider(ctx context.Context, userID, provider, subject string, email *string) error

func (*Service) LinkProviderByIssuer

func (s *Service) LinkProviderByIssuer(ctx context.Context, userID, issuer, providerSlug, subject string, email *string) error

func (*Service) LinkSolanaWallet

func (s *Service) LinkSolanaWallet(ctx context.Context, cache siws.ChallengeCache, userID string, output siws.SignInOutput) error

LinkSolanaWallet links a Solana wallet to an existing user account.

func (*Service) ListEntitlements

func (s *Service) ListEntitlements(ctx context.Context, userID string) []string

ListEntitlements returns current entitlements for a user (fresh from provider).

func (*Service) ListEntitlementsDetailed

func (s *Service) ListEntitlementsDetailed(ctx context.Context, userID string) []entpg.Entitlement

ListEntitlementsDetailed returns detailed entitlements (name + metadata).

func (*Service) ListOrgDefinedRoles added in v0.4.4

func (s *Service) ListOrgDefinedRoles(ctx context.Context, orgSlug string) ([]string, error)

func (*Service) ListOrgMembers added in v0.4.4

func (s *Service) ListOrgMembers(ctx context.Context, orgSlug string) ([]string, error)

func (*Service) ListOrgMembershipsForUser added in v0.4.4

func (s *Service) ListOrgMembershipsForUser(ctx context.Context, userID string) ([]string, error)

func (*Service) ListRoleSlugsByUser

func (s *Service) ListRoleSlugsByUser(ctx context.Context, userID string) []string

Public helpers for HTTP adapters

func (*Service) ListUserOrgMembershipsAndRoles added in v0.4.4

func (s *Service) ListUserOrgMembershipsAndRoles(ctx context.Context, userID string) ([]OrgMembership, error)

func (*Service) ListUserSessions

func (s *Service) ListUserSessions(ctx context.Context, userID string) ([]Session, error)

ListUserSessions lists active sessions for a user and issuer.

func (*Service) ListUsersDeletedBefore

func (s *Service) ListUsersDeletedBefore(ctx context.Context, cutoff time.Time, limit int) ([]string, error)

ListUsersDeletedBefore returns user IDs for users soft-deleted before the cutoff. It is intended for retention/purge workflows in the host application.

func (*Service) LogPasswordChanged added in v0.4.2

func (s *Service) LogPasswordChanged(ctx context.Context, userID string, sessionID string, ip *string, ua *string)

LogPasswordChanged records a password change event for a user (best-effort).

func (*Service) LogPasswordRecovery added in v0.4.2

func (s *Service) LogPasswordRecovery(ctx context.Context, userID string, method, sessionID string, ip *string, ua *string)

func (*Service) LogSessionCreated

func (s *Service) LogSessionCreated(ctx context.Context, userID string, method string, sessionID string, ip *string, ua *string)

LogSessionCreated records a session creation event via the configured AuthEventLogger (best-effort).

func (*Service) LogSessionFailed added in v0.4.2

func (s *Service) LogSessionFailed(ctx context.Context, userID string, sessionID string, reason *string, ip *string, ua *string)

func (*Service) Options

func (s *Service) Options() Options

Options exposes immutable configuration for callers that need to validate claims.

func (*Service) PasswordLogin

func (s *Service) PasswordLogin(ctx context.Context, email, pass string, extra map[string]any) (string, time.Time, error)

PasswordLogin verifies credentials and issues an ID token.

func (*Service) PasswordLoginByUserID

func (s *Service) PasswordLoginByUserID(ctx context.Context, userID, pass string, extra map[string]any) (string, time.Time, error)

PasswordLoginByUserID verifies credentials for a specific user ID and issues an ID token. This supports login flows where the identifier is a phone number or username and email may be NULL.

func (*Service) Postgres

func (s *Service) Postgres() *pgxpool.Pool

Postgres returns the attached pgx pool (may be nil).

func (*Service) ReadMemberRoles added in v0.4.4

func (s *Service) ReadMemberRoles(ctx context.Context, orgSlug, userID string) ([]string, error)

func (*Service) RegenerateBackupCodes

func (s *Service) RegenerateBackupCodes(ctx context.Context, userID string) ([]string, error)

RegenerateBackupCodes generates new backup codes for a user (invalidating old ones). Returns the plaintext codes (caller must show these to user ONCE).

func (*Service) RemoveMember added in v0.4.4

func (s *Service) RemoveMember(ctx context.Context, orgSlug, userID string) error

func (*Service) RemoveRoleBySlug

func (s *Service) RemoveRoleBySlug(ctx context.Context, userID, slug string) error

func (*Service) RenameOrgSlug added in v0.4.4

func (s *Service) RenameOrgSlug(ctx context.Context, orgID, newSlug string) error

func (*Service) RequestEmailChange

func (s *Service) RequestEmailChange(ctx context.Context, userID, newEmail string) error

RequestEmailChange initiates an email change by sending a verification code to the new email. The current email is NOT changed until the user confirms via ConfirmEmailChange. Also sends a notification to the old email for security.

func (*Service) RequestEmailVerification

func (s *Service) RequestEmailVerification(ctx context.Context, email string, ttl time.Duration) error

RequestEmailVerification creates a verification code and dispatches an email. Always returns 202-like behavior.

func (*Service) RequestPasswordReset

func (s *Service) RequestPasswordReset(ctx context.Context, email string, ttl time.Duration) error

RequestPasswordReset creates a password reset token and dispatches a reset link via email. Returns nil for unknown emails to prevent user enumeration (202-like behavior).

func (*Service) RequestPhoneChange

func (s *Service) RequestPhoneChange(ctx context.Context, userID, newPhone string) error

RequestPhoneChange initiates a phone number change by sending a verification code to the new phone. The current phone is NOT changed until the user confirms via ConfirmPhoneChange.

func (*Service) RequestPhonePasswordReset

func (s *Service) RequestPhonePasswordReset(ctx context.Context, phone string, ttl time.Duration) error

RequestPhonePasswordReset creates a password reset token and sends a reset link via SMS. Always returns nil for unknown phone numbers to prevent user enumeration (202-like behavior).

func (*Service) RequestPhoneVerification

func (s *Service) RequestPhoneVerification(ctx context.Context, phone string, ttl time.Duration) error

RequestPhoneVerification looks up the user by phone number and sends a verification code. This mirrors the RequestEmailVerification pattern - caller only needs to provide the phone number. Always returns nil for security (prevents phone enumeration).

func (*Service) Require2FAForLogin

func (s *Service) Require2FAForLogin(ctx context.Context, userID string) (string, error)

Require2FAForLogin sends a 2FA code to the user's configured method. Returns the destination (email/phone) where the code was sent. This should be called after successful password verification.

func (*Service) ResendEmailChangeCode

func (s *Service) ResendEmailChangeCode(ctx context.Context, userID string) error

ResendEmailChangeCode resends the verification code for a pending email change.

func (*Service) ResendPhoneChangeCode

func (s *Service) ResendPhoneChangeCode(ctx context.Context, userID, phone string) error

ResendPhoneChangeCode resends the verification code for a pending phone change.

func (*Service) ResolveOrgBySlug added in v0.4.4

func (s *Service) ResolveOrgBySlug(ctx context.Context, slug string) (*Org, error)

ResolveOrgBySlug resolves an org by current slug or alias. Returns ErrOrgNotFound when no org matches.

func (*Service) ResolveSessionByRefresh

func (s *Service) ResolveSessionByRefresh(ctx context.Context, refreshToken string) (string, error)

ResolveSessionByRefresh finds the session id for a presented refresh token, if valid and active.

func (*Service) RestoreUser

func (s *Service) RestoreUser(ctx context.Context, id string) error

RestoreUser clears deleted_at and re-enables the account.

func (*Service) RevokeAllSessions

func (s *Service) RevokeAllSessions(ctx context.Context, userID string, keepSessionID *string) error

func (*Service) RevokeSessionByID

func (s *Service) RevokeSessionByID(ctx context.Context, sessionID string) error

func (*Service) RevokeSessionByIDForUser

func (s *Service) RevokeSessionByIDForUser(ctx context.Context, userID, sessionID string) error

RevokeSessionByIDForUser revokes a session by id ensuring it belongs to the user.

func (*Service) SendPhone2FASetupCode

func (s *Service) SendPhone2FASetupCode(ctx context.Context, userID, phone, code string) error

SendPhone2FASetupCode generates and sends a 6-digit code for 2FA setup to the user's phone.

func (*Service) SendPhoneVerificationToUser

func (s *Service) SendPhoneVerificationToUser(ctx context.Context, phone, userID string, ttl time.Duration) error

SendPhoneVerificationToUser creates a verification code and sends it via SMS to a known user. Use RequestPhoneVerification if you only have a phone number and need to look up the user. Always returns nil for security.

func (*Service) SendWelcome

func (s *Service) SendWelcome(ctx context.Context, userID string)

SendWelcome triggers the welcome email if an EmailSender is configured.

func (*Service) SetEmailVerified

func (s *Service) SetEmailVerified(ctx context.Context, id string, v bool) error

func (*Service) SetProviderUsername

func (s *Service) SetProviderUsername(ctx context.Context, userID, provider, subject, username string) error

func (*Service) SoftDeleteUser

func (s *Service) SoftDeleteUser(ctx context.Context, id string) error

SoftDeleteUser marks the user deleted and sets deleted_at without dropping rows. Also revokes all refresh sessions for this issuer.

func (*Service) UnassignRole added in v0.4.4

func (s *Service) UnassignRole(ctx context.Context, orgSlug, userID, role string) error

func (*Service) UnbanUser

func (s *Service) UnbanUser(ctx context.Context, userID string) error

UnbanUser clears ban metadata and re-enables the account.

func (*Service) UnlinkProvider

func (s *Service) UnlinkProvider(ctx context.Context, userID, provider string) error

func (*Service) UpdateBiography

func (s *Service) UpdateBiography(ctx context.Context, id string, bio *string) error

func (*Service) UpdateEmail

func (s *Service) UpdateEmail(ctx context.Context, id, email string) error

func (*Service) UpdateUsername

func (s *Service) UpdateUsername(ctx context.Context, id, username string) error

func (*Service) UpsertPasswordHash

func (s *Service) UpsertPasswordHash(ctx context.Context, userID, hash, algo string, params []byte) error

func (*Service) Verify2FAChallenge

func (s *Service) Verify2FAChallenge(ctx context.Context, userID, challenge string) (bool, error)

Verify2FAChallenge verifies the challenge created during the password step.

func (*Service) Verify2FACode

func (s *Service) Verify2FACode(ctx context.Context, userID, code string) (bool, error)

Verify2FACode verifies a 2FA code entered by the user during login. Returns true if code is valid, false otherwise.

func (*Service) VerifyBackupCode

func (s *Service) VerifyBackupCode(ctx context.Context, userID, backupCode string) (bool, error)

VerifyBackupCode verifies a 2FA backup code for account recovery. On success, removes the used backup code from the user's backup codes.

func (*Service) VerifyPendingPassword

func (s *Service) VerifyPendingPassword(ctx context.Context, email, pass string) bool

VerifyPendingPassword checks if the provided password matches the pending registration's hash. Returns true if password is correct, false otherwise.

func (*Service) VerifyPhone2FASetupCode

func (s *Service) VerifyPhone2FASetupCode(ctx context.Context, userID, phone, code string) (bool, error)

VerifyPhone2FASetupCode checks the code for 2FA phone setup.

func (*Service) VerifySIWSAndLogin

func (s *Service) VerifySIWSAndLogin(ctx context.Context, cache siws.ChallengeCache, output siws.SignInOutput, extra map[string]any) (accessToken string, expiresAt time.Time, refreshToken, userID string, created bool, err error)

VerifySIWSAndLogin verifies a SIWS signature and logs in or creates a user. Returns access token, expiry, refresh token, user ID, and whether a new user was created.

func (*Service) WithAuthLogger

func (s *Service) WithAuthLogger(l AuthEventLogger) *Service

WithAuthLogger sets the authentication event logger (e.g., ClickHouse sink).

func (*Service) WithEmailSender

func (s *Service) WithEmailSender(sender EmailSender) *Service

WithEmailSender sets the email sender dependency.

func (*Service) WithEntitlements

func (s *Service) WithEntitlements(p EntitlementsProvider) *Service

WithEntitlements sets the entitlements provider.

func (*Service) WithEphemeralStore

func (s *Service) WithEphemeralStore(store EphemeralStore, mode EphemeralMode) *Service

func (*Service) WithPostgres

func (s *Service) WithPostgres(pool *pgxpool.Pool) *Service

WithPostgres attaches a pgx pool to the service.

func (*Service) WithSMSSender

func (s *Service) WithSMSSender(sender SMSSender) *Service

WithSMSSender sets the SMS sender dependency.

type Session

type Session struct {
	ID         string
	FamilyID   string
	CreatedAt  time.Time
	LastUsedAt time.Time
	ExpiresAt  *time.Time
	RevokedAt  *time.Time
	UserAgent  *string
	IPAddr     *string
}

Session represents a sanitized session view (no tokens).

type SessionEventType

type SessionEventType string

SessionEventType identifies a session lifecycle event.

const (
	SessionEventCreated          SessionEventType = "session_created"
	SessionEventRevoked          SessionEventType = "session_revoked"
	SessionEventPasswordChange   SessionEventType = "password_changed"
	SessionEventPasswordRecovery SessionEventType = "password_recovery"
	SessionEventFailed           SessionEventType = "session_failed"
)

type SessionRevokeReason

type SessionRevokeReason string

SessionRevokeReason identifies why a session (or set of sessions) was revoked.

const (
	SessionRevokeReasonUnknown              SessionRevokeReason = ""
	SessionRevokeReasonLogout               SessionRevokeReason = "logout"
	SessionRevokeReasonUserRevoke           SessionRevokeReason = "user_revoke"
	SessionRevokeReasonUserRevokeAll        SessionRevokeReason = "user_revoke_all"
	SessionRevokeReasonAdminRevoke          SessionRevokeReason = "admin_revoke"
	SessionRevokeReasonAdminRevokeAll       SessionRevokeReason = "admin_revoke_all"
	SessionRevokeReasonPasswordChange       SessionRevokeReason = "password_change"
	SessionRevokeReasonAdminSetPassword     SessionRevokeReason = "admin_set_password"
	SessionRevokeReasonUserDisabled         SessionRevokeReason = "user_disabled"
	SessionRevokeReasonBanned               SessionRevokeReason = "banned"
	SessionRevokeReasonSoftDeleted          SessionRevokeReason = "soft_deleted"
	SessionRevokeReasonEvicted              SessionRevokeReason = "evicted"
	SessionRevokeReasonRefreshReuseDetected SessionRevokeReason = "refresh_reuse_detected"
)

type TwoFactorSettings

type TwoFactorSettings struct {
	UserID      string
	Enabled     bool
	Method      string // "email" or "sms"
	PhoneNumber *string
	BackupCodes []string // Hashed backup codes
	CreatedAt   time.Time
	UpdatedAt   time.Time
}

TwoFactorSettings represents a user's 2FA configuration

type User

type User struct {
	ID              string
	Email           *string // Nullable - phone-only users have NULL email
	PhoneNumber     *string
	Username        *string
	DiscordUsername *string
	EmailVerified   bool
	PhoneVerified   bool
	BannedAt        *time.Time
	BannedUntil     *time.Time
	BanReason       *string
	BannedBy        *string
	DeletedAt       *time.Time
	Biography       *string
	CreatedAt       time.Time
	UpdatedAt       time.Time
	LastLogin       *time.Time
}

type Verifier

type Verifier interface {
	JWKS() jwtkit.JWKS
	Keyfunc() func(token *jwt.Token) (any, error)
	Options() Options

	// Optional enrichment hooks (best-effort).
	// Middleware can use these to fetch fresh roles/usernames when available.
	ListRoleSlugsByUser(ctx context.Context, userID string) []string
	GetProviderUsername(ctx context.Context, userID, provider string) (string, error)
}

Verifier is the minimal surface needed to validate JWT access tokens.

It intentionally avoids exposing storage/transport details; implementations may be fully stateless (JWKS-only) or service-backed.

Jump to

Keyboard shortcuts

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