core

package
v0.0.74 Latest Latest
Warning

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

Go to latest
Published: Apr 17, 2026 License: Apache-2.0 Imports: 12 Imported by: 2

Documentation

Overview

Package core provides the foundation types and interfaces for the OneAuth authentication framework. Every other OneAuth package imports core.

The core package contains:

  • User, Identity, and Channel types (the data model)
  • Store interfaces (UserStore, IdentityStore, ChannelStore, etc.)
  • Token types and token store interface
  • Credentials, signup policies, and validation types
  • Scope constants and helpers
  • Email sender interface
  • Request context helpers (GetUserIDFromContext, SetUserIDInContext)

Index

Constants

View Source
const (
	ErrCodeEmailExists     = "email_exists"
	ErrCodeUsernameTaken   = "username_taken"
	ErrCodeWeakPassword    = "weak_password"
	ErrCodeInvalidUsername = "invalid_username"
	ErrCodeInvalidEmail    = "invalid_email"
	ErrCodeInvalidPhone    = "invalid_phone"
	ErrCodeMissingField    = "missing_field"
	ErrCodeInvalidCreds    = "invalid_credentials"
)

Common error codes

View Source
const (
	ScopeRead    = "read"    // Read access to user data
	ScopeWrite   = "write"   // Write access to user data
	ScopeProfile = "profile" // Access to user profile information
	ScopeOffline = "offline" // Enable refresh tokens (long-lived sessions)
	ScopeAdmin   = "admin"   // Administrative access
)

Built-in scope constants

View Source
const (
	TokenExpiryEmailVerification = 24 * time.Hour     // 24 hours
	TokenExpiryPasswordReset     = 1 * time.Hour      // 1 hour
	TokenExpiryAccessToken       = 15 * time.Minute   // 15 minutes
	TokenExpiryRefreshToken      = 7 * 24 * time.Hour // 7 days
)

Default token expiry durations

View Source
const DefaultUserParamName = "loggedInUserId"

DefaultUserParamName is the default context key for user ID

Variables

View Source
var (
	ErrTokenNotFound  = fmt.Errorf("token not found")
	ErrTokenExpired   = fmt.Errorf("token expired")
	ErrTokenRevoked   = fmt.Errorf("token revoked")
	ErrTokenReused    = fmt.Errorf("token reuse detected")
	ErrInvalidGrant   = fmt.Errorf("invalid grant")
	ErrInvalidScope   = fmt.Errorf("invalid scope")
	ErrAPIKeyNotFound = fmt.Errorf("api key not found")
)

Common errors for token operations

View Source
var PolicyEmailOnly = SignupPolicy{
	RequireUsername:       false,
	RequireEmail:          true,
	RequirePhone:          false,
	RequirePassword:       true,
	EnforceUsernameUnique: true,
	EnforceEmailUnique:    true,
	MinPasswordLength:     8,
	UsernamePattern:       `^[a-zA-Z0-9_-]{3,20}$`,
}

PolicyEmailOnly requires only email and password for signup (username optional)

View Source
var PolicyFlexible = SignupPolicy{
	RequireUsername:       false,
	RequireEmail:          false,
	RequirePhone:          false,
	RequirePassword:       false,
	EnforceUsernameUnique: true,
	EnforceEmailUnique:    true,
	MinPasswordLength:     8,
	UsernamePattern:       `^[a-zA-Z0-9_-]{3,20}$`,
}

PolicyFlexible is OAuth-friendly - email/phone optional, username optional

View Source
var PolicyUsernameRequired = SignupPolicy{
	RequireUsername:       true,
	RequireEmail:          true,
	RequirePhone:          false,
	RequirePassword:       true,
	EnforceUsernameUnique: true,
	EnforceEmailUnique:    true,
	MinPasswordLength:     8,
	UsernamePattern:       `^[a-zA-Z0-9_-]{3,20}$`,
}

PolicyUsernameRequired requires username, email, and password for signup

Functions

func AllBuiltinScopes

func AllBuiltinScopes() []string

AllBuiltinScopes returns all built-in scope values

func ContainsAllScopes

func ContainsAllScopes(granted, required []string) bool

ContainsAllScopes checks if all required scopes are present in the granted scopes

func ContainsScope

func ContainsScope(scopes []string, scope string) bool

ContainsScope checks if a scope is present in the list

func DetectUsernameType

func DetectUsernameType(username string) string

DetectUsernameType attempts to detect what type of username was provided

func GenerateAPIKeyID

func GenerateAPIKeyID() (string, error)

GenerateAPIKeyID generates a new API key ID with prefix

func GenerateAPIKeySecret

func GenerateAPIKeySecret() (string, error)

GenerateAPIKeySecret generates the secret portion of an API key

func GenerateSecureToken

func GenerateSecureToken() (string, error)

GenerateSecureToken generates a cryptographically secure random token

func GetUserIDFromContext

func GetUserIDFromContext(ctx context.Context) string

GetUserIDFromContext retrieves the user ID from the request context Uses the default key "loggedInUserId"

func IdentityKey

func IdentityKey(identityType, identityValue string) string

IdentityKey creates a consistent identity key from type and value

func IntersectScopes

func IntersectScopes(requested, allowed []string) []string

IntersectScopes returns the intersection of requested and allowed scopes The result contains only scopes that appear in both slices

func JoinScopes

func JoinScopes(scopes []string) string

JoinScopes joins a slice of scopes into a space-separated string

func ParseScopes

func ParseScopes(scopeString string) []string

ParseScopes parses a space-separated scope string into a slice

func ScopesEqual

func ScopesEqual(a, b []string) bool

ScopesEqual checks if two scope slices contain the same scopes (order-independent)

func SetUserIDInContext

func SetUserIDInContext(ctx context.Context, userID string) context.Context

SetUserIDInContext sets the user ID in the request context

func UnionScopes added in v0.0.68

func UnionScopes(a, b []string) []string

UnionScopes returns the union of two scope slices, deduplicated and sorted. This is the complement of IntersectScopes — use UnionScopes to merge scope sets (e.g., combining existing and newly requested scopes), and IntersectScopes to restrict scope sets (e.g., filtering requested scopes against allowed scopes).

func ValidateRequestedScopes

func ValidateRequestedScopes(requested, allowed []string) (valid, invalid []string)

ValidateRequestedScopes validates that all requested scopes are from the allowed set Returns the valid scopes and any invalid scopes found

Types

type APIKey

type APIKey struct {
	KeyID      string     `json:"key_id"`   // Public identifier (e.g., "oa_abc123...")
	KeyHash    string     `json:"key_hash"` // bcrypt hash of the secret portion
	UserID     string     `json:"user_id"`  // Owner of this key
	Name       string     `json:"name"`     // User-defined label
	Scopes     []string   `json:"scopes"`   // Allowed scopes
	CreatedAt  time.Time  `json:"created_at"`
	ExpiresAt  *time.Time `json:"expires_at,omitempty"` // Optional expiry
	LastUsedAt time.Time  `json:"last_used_at"`
	RevokedAt  *time.Time `json:"revoked_at,omitempty"`
	Revoked    bool       `json:"revoked"`
}

APIKey represents a long-lived API key for programmatic access

func (*APIKey) IsExpired

func (k *APIKey) IsExpired() bool

IsExpired checks if an API key has expired

func (*APIKey) IsValid

func (k *APIKey) IsValid() bool

IsValid checks if an API key is valid (not expired and not revoked)

type APIKeyStore

type APIKeyStore interface {
	// CreateAPIKey creates a new API key and returns the full key (only shown once)
	// The key format is: keyID + "_" + secret
	CreateAPIKey(userID, name string, scopes []string, expiresAt *time.Time) (fullKey string, apiKey *APIKey, err error)

	// GetAPIKeyByID retrieves an API key by its public ID
	GetAPIKeyByID(keyID string) (*APIKey, error)

	// ValidateAPIKey validates a full API key and returns the key metadata if valid
	// The fullKey format is: keyID + "_" + secret
	ValidateAPIKey(fullKey string) (*APIKey, error)

	// RevokeAPIKey marks an API key as revoked
	RevokeAPIKey(keyID string) error

	// ListUserAPIKeys returns all API keys for a user (without secrets)
	ListUserAPIKeys(userID string) ([]*APIKey, error)

	// UpdateAPIKeyLastUsed updates the last used timestamp
	UpdateAPIKeyLastUsed(keyID string) error
}

APIKeyStore manages API keys for programmatic access

type AccountLockout added in v0.0.44

type AccountLockout struct {
	MaxAttempts  int           // consecutive failures before lockout (default: 5)
	LockDuration time.Duration // how long the lockout lasts (default: 15 min)
	// contains filtered or unexported fields
}

AccountLockout tracks consecutive authentication failures per key and locks accounts after a configurable number of attempts. Lockouts expire automatically after LockDuration. Thread-safe.

func NewAccountLockout added in v0.0.44

func NewAccountLockout(maxAttempts int, lockDuration time.Duration) *AccountLockout

NewAccountLockout creates an AccountLockout with the given thresholds.

func (*AccountLockout) IsLocked added in v0.0.44

func (l *AccountLockout) IsLocked(key string) bool

IsLocked returns true if the key is currently locked out.

func (*AccountLockout) RecordFailure added in v0.0.44

func (l *AccountLockout) RecordFailure(key string) bool

RecordFailure records a failed authentication attempt. Returns true if the account is now locked (threshold reached).

func (*AccountLockout) RecordSuccess added in v0.0.44

func (l *AccountLockout) RecordSuccess(key string)

RecordSuccess resets the failure counter for a key (successful login).

func (*AccountLockout) Reset added in v0.0.44

func (l *AccountLockout) Reset(key string)

Reset unlocks an account (admin action).

type AuthError

type AuthError struct {
	Code    string // "email_exists", "username_taken", "weak_password", "invalid_format", etc.
	Message string // Human-readable message
	Field   string // Which form field has the error (e.g., "email", "username", "password")
}

AuthError represents a structured authentication error

func NewAuthError

func NewAuthError(code, message, field string) *AuthError

NewAuthError creates a new AuthError

func (*AuthError) Error

func (e *AuthError) Error() string

type AuthErrorHandler

type AuthErrorHandler func(err *AuthError, w http.ResponseWriter, r *http.Request) bool

AuthErrorHandler is called when authentication errors occur. The handler receives the structured error and should write the response. Returns true if the error was handled (response written), false to use default JSON response.

Example implementations:

  • Redirect back to form with flash message (app uses their session library)
  • Redirect with error in query params: /signup?error=email_exists
  • Return JSON error response
  • Log and show generic error page

type AuthToken

type AuthToken struct {
	Token     string    `json:"token"`
	Type      TokenType `json:"type"`
	UserID    string    `json:"user_id"`
	Email     string    `json:"email"`
	CreatedAt time.Time `json:"created_at"`
	ExpiresAt time.Time `json:"expires_at"`
}

AuthToken represents a verification or reset token

func (*AuthToken) IsExpired

func (t *AuthToken) IsExpired() bool

IsExpired checks if a token has expired

func (*AuthToken) IsValid

func (t *AuthToken) IsValid(expectedType TokenType) bool

IsValid checks if a token is valid (not expired and matches type)

type BasicUser

type BasicUser struct {
	ID          string
	ProfileData map[string]any
}

BasicUser is a simple implementation of the User interface

func (*BasicUser) Id

func (b *BasicUser) Id() string

func (*BasicUser) Profile

func (b *BasicUser) Profile() map[string]any

type Channel

type Channel struct {
	Provider    string         `json:"provider"`     // "local", "google", "github"
	IdentityKey string         `json:"identity_key"` // "email:john@example.com"
	Credentials map[string]any `json:"credentials"`  // password_hash, access_token, etc.
	Profile     map[string]any `json:"profile"`      // optional data from provider
	CreatedAt   time.Time      `json:"created_at"`
	UpdatedAt   time.Time      `json:"updated_at"`
	ExpiresAt   time.Time      `json:"expires_at"` // when channel auth expires and needs re-auth
	Version     int            `json:"version"`    // optimistic locking version
}

Channel represents an authentication mechanism/provider

func (*Channel) IsExpired

func (c *Channel) IsExpired() bool

IsExpired returns true if the channel has an expiration time set and it has passed

type ChannelStore

type ChannelStore interface {
	// GetChannel gets or optionally creates a channel
	GetChannel(provider string, identityKey string, createIfMissing bool) (channel *Channel, newCreated bool, err error)

	// SaveChannel creates or updates a channel (upsert)
	SaveChannel(channel *Channel) error

	// GetChannelsByIdentity returns all channels for an identity
	GetChannelsByIdentity(identityKey string) ([]*Channel, error)
}

ChannelStore manages authentication channels/providers

type ConsoleEmailSender

type ConsoleEmailSender struct{}

ConsoleEmailSender is a development implementation that logs emails to console

func (*ConsoleEmailSender) SendPasswordResetEmail

func (c *ConsoleEmailSender) SendPasswordResetEmail(to string, resetLink string) error

func (*ConsoleEmailSender) SendVerificationEmail

func (c *ConsoleEmailSender) SendVerificationEmail(to string, verificationLink string) error

type CreateUserFunc

type CreateUserFunc func(creds *Credentials) (User, error)

CreateUserFunc creates a new user with the given credentials

type Credentials

type Credentials struct {
	Username string  // Required for signup, can be username/email/phone for login
	Email    *string // Optional for signup
	Phone    *string // Optional for signup
	Password string  // Required
}

Credentials represents user credentials for signup or login

type CredentialsValidator

type CredentialsValidator func(username, password, usernameType string) (User, error)

CredentialsValidator validates credentials during login and returns the user

type GetUserScopesFunc

type GetUserScopesFunc func(userID string) ([]string, error)

GetUserScopesFunc is a callback that returns allowed scopes for a user. Applications implement this to determine what scopes a user is allowed to have. This can be based on user roles, profile data, groups, etc.

func DefaultGetUserScopes

func DefaultGetUserScopes() GetUserScopesFunc

DefaultGetUserScopes returns a default implementation that grants basic scopes to all users

type HandleUserFunc

type HandleUserFunc func(authtype string, provider string, token *oauth2.Token, userInfo map[string]any, w http.ResponseWriter, r *http.Request)

HandleUserFunc is called after successful authentication (OAuth or local).

type Identity

type Identity struct {
	Type      string    `json:"type"`     // "email", "phone"
	Value     string    `json:"value"`    // "john@example.com", "+1-555-1234"
	UserID    string    `json:"user_id"`  // which user owns this identity
	Verified  bool      `json:"verified"` // has any channel verified this identity?
	CreatedAt time.Time `json:"created_at"`
	UpdatedAt time.Time `json:"updated_at"`
	Version   int       `json:"version"` // optimistic locking version
}

Identity represents a contact method (email, phone) that can be verified

type IdentityStore

type IdentityStore interface {
	// GetIdentity gets or optionally creates an identity
	GetIdentity(identityType, identityValue string, createIfMissing bool) (identity *Identity, newCreated bool, err error)

	// SaveIdentity creates or updates an identity (upsert)
	SaveIdentity(identity *Identity) error

	// SetUserForIdentity associates an identity with a user
	SetUserForIdentity(identityType, identityValue string, newUserId string) error

	// MarkIdentityVerified marks an identity as verified
	MarkIdentityVerified(identityType, identityValue string) error

	// GetUserIdentities returns all identities for a user
	GetUserIdentities(userId string) ([]*Identity, error)
}

IdentityStore manages contact identities (email, phone)

type InMemoryBlacklist added in v0.0.48

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

InMemoryBlacklist is a thread-safe in-memory TokenBlacklist. Suitable for single-process deployments. For distributed deployments, use a Redis-backed implementation with the same interface.

func NewInMemoryBlacklist added in v0.0.48

func NewInMemoryBlacklist() *InMemoryBlacklist

NewInMemoryBlacklist creates a new in-memory blacklist.

func (*InMemoryBlacklist) CleanupExpired added in v0.0.48

func (b *InMemoryBlacklist) CleanupExpired()

CleanupExpired removes entries whose tokens have naturally expired. Call periodically (e.g., every minute) to prevent memory growth.

func (*InMemoryBlacklist) IsRevoked added in v0.0.48

func (b *InMemoryBlacklist) IsRevoked(jti string) bool

IsRevoked returns true if the token ID is in the blacklist and hasn't expired.

func (*InMemoryBlacklist) Len added in v0.0.48

func (b *InMemoryBlacklist) Len() int

Len returns the number of entries (including expired ones not yet cleaned).

func (*InMemoryBlacklist) Revoke added in v0.0.48

func (b *InMemoryBlacklist) Revoke(jti string, expiry time.Time) error

Revoke adds a token ID to the blacklist until its expiry time.

type InMemoryRateLimiter added in v0.0.44

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

InMemoryRateLimiter implements RateLimiter using a token bucket algorithm. Each key gets an independent bucket that refills at a steady rate. Thread-safe for concurrent use.

func NewInMemoryRateLimiter added in v0.0.44

func NewInMemoryRateLimiter(rate float64, burst int) *InMemoryRateLimiter

NewInMemoryRateLimiter creates a rate limiter that allows `rate` requests per second with a burst capacity of `burst`.

Example: NewInMemoryRateLimiter(0.5, 5) allows 1 request per 2 seconds sustained, with bursts of up to 5 requests.

func (*InMemoryRateLimiter) Allow added in v0.0.44

func (r *InMemoryRateLimiter) Allow(key string) bool

Allow returns true if the key has tokens remaining.

func (*InMemoryRateLimiter) CleanupStale added in v0.0.44

func (r *InMemoryRateLimiter) CleanupStale(maxAge time.Duration)

CleanupStale removes buckets that haven't been used for the given duration. Call periodically to prevent memory growth from abandoned keys.

type RateLimiter added in v0.0.44

type RateLimiter interface {
	// Allow returns true if the operation is permitted for the given key.
	// Returns false if the rate limit has been exceeded.
	Allow(key string) bool
}

RateLimiter controls the rate of operations (e.g., login attempts) per key. Keys are typically IP addresses, usernames, or a combination.

type RefreshToken

type RefreshToken struct {
	Token      string         `json:"token"`       // 64-char hex token value
	TokenHash  string         `json:"token_hash"`  // SHA256 hash for storage (optional)
	UserID     string         `json:"user_id"`     // Associated user
	ClientID   string         `json:"client_id"`   // Optional client/app identifier
	DeviceInfo map[string]any `json:"device_info"` // User agent, IP, etc.
	Family     string         `json:"family"`      // Token family for rotation tracking
	Generation int            `json:"generation"`  // Increments on rotation
	Scopes     []string       `json:"scopes"`      // Granted scopes
	CreatedAt  time.Time      `json:"created_at"`
	ExpiresAt  time.Time      `json:"expires_at"`
	LastUsedAt time.Time      `json:"last_used_at"`
	RevokedAt  *time.Time     `json:"revoked_at,omitempty"`
	Revoked    bool           `json:"revoked"`
}

RefreshToken represents a long-lived refresh token for API access

func (*RefreshToken) IsExpired

func (t *RefreshToken) IsExpired() bool

IsExpired checks if a refresh token has expired

func (*RefreshToken) IsValid

func (t *RefreshToken) IsValid() bool

IsValid checks if a refresh token is valid (not expired and not revoked)

type RefreshTokenStore

type RefreshTokenStore interface {
	// CreateRefreshToken creates a new refresh token for a user
	CreateRefreshToken(userID, clientID string, deviceInfo map[string]any, scopes []string) (*RefreshToken, error)

	// GetRefreshToken retrieves a refresh token by its value
	GetRefreshToken(token string) (*RefreshToken, error)

	// RotateRefreshToken invalidates old token and creates new one in same family
	// Returns ErrTokenReused if the old token was already revoked (theft detection)
	RotateRefreshToken(oldToken string) (*RefreshToken, error)

	// RevokeRefreshToken marks a token as revoked
	RevokeRefreshToken(token string) error

	// RevokeUserTokens revokes all refresh tokens for a user
	RevokeUserTokens(userID string) error

	// RevokeTokenFamily revokes all tokens in a family (theft detection)
	RevokeTokenFamily(family string) error

	// GetUserTokens lists all active (non-revoked, non-expired) refresh tokens for a user
	GetUserTokens(userID string) ([]*RefreshToken, error)

	// CleanupExpiredTokens removes expired tokens (for maintenance)
	CleanupExpiredTokens() error
}

RefreshTokenStore manages refresh tokens for API access

type SendEmail

type SendEmail interface {
	SendVerificationEmail(to string, verificationLink string) error
	SendPasswordResetEmail(to string, resetLink string) error
}

SendEmail interface allows applications to provide their own email sending implementation

type SignupPolicy

type SignupPolicy struct {
	RequireUsername       bool   // Is username required? (default: false)
	RequireEmail          bool   // Is email required? (default: true)
	RequirePhone          bool   // Is phone required? (default: false)
	RequirePassword       bool   // Is password required for local? (default: true)
	EnforceUsernameUnique bool   // Check UsernameStore? (default: true if username required)
	EnforceEmailUnique    bool   // Check IdentityStore? (default: true)
	MinPasswordLength     int    // Minimum password (default: 8)
	UsernamePattern       string // Regex for username (default: ^[a-zA-Z0-9_-]{3,20}$)
}

SignupPolicy defines what is required for signup

func DefaultSignupPolicy

func DefaultSignupPolicy() SignupPolicy

DefaultSignupPolicy returns a sensible default signup policy

func (SignupPolicy) GetMinPasswordLength

func (p SignupPolicy) GetMinPasswordLength() int

GetMinPasswordLength returns the minimum password length

func (SignupPolicy) GetUsernamePattern

func (p SignupPolicy) GetUsernamePattern() *regexp.Regexp

GetUsernamePattern returns the compiled username regex pattern

type SignupValidator

type SignupValidator func(creds *Credentials) error

SignupValidator validates credentials during signup

var DefaultSignupValidator SignupValidator = func(creds *Credentials) error {

	if len(creds.Username) < 3 || len(creds.Username) > 20 {
		return fmt.Errorf("username must be 3-20 characters")
	}
	usernameRegex := regexp.MustCompile(`^[a-zA-Z0-9_-]+$`)
	if !usernameRegex.MatchString(creds.Username) {
		return fmt.Errorf("username can only contain letters, numbers, underscores, and hyphens")
	}

	if creds.Email == nil && creds.Phone == nil {
		return fmt.Errorf("email or phone required")
	}

	if creds.Email != nil && *creds.Email != "" {
		emailRegex := regexp.MustCompile(`^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$`)
		if !emailRegex.MatchString(*creds.Email) {
			return fmt.Errorf("invalid email format")
		}
	}

	if creds.Phone != nil && *creds.Phone != "" {
		cleaned := strings.ReplaceAll(*creds.Phone, "-", "")
		cleaned = strings.ReplaceAll(cleaned, " ", "")
		cleaned = strings.ReplaceAll(cleaned, "(", "")
		cleaned = strings.ReplaceAll(cleaned, ")", "")
		if len(cleaned) < 10 {
			return fmt.Errorf("invalid phone number")
		}
	}

	if len(creds.Password) < 8 {
		return fmt.Errorf("password must be at least 8 characters")
	}

	return nil
}

DefaultSignupValidator provides sensible default validation for signup

type TokenBlacklist added in v0.0.48

type TokenBlacklist interface {
	// Revoke adds a token ID to the blacklist. The entry should be kept
	// until expiry (when the token would naturally expire anyway).
	Revoke(jti string, expiry time.Time) error

	// IsRevoked returns true if the token ID has been revoked and hasn't expired.
	IsRevoked(jti string) bool
}

TokenBlacklist tracks revoked JWT access tokens by their jti (JWT ID) claim. Entries auto-expire when the original token would have expired, preventing unbounded growth. Pluggable: in-memory for single-node, Redis for distributed.

See: https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.7

type TokenError

type TokenError struct {
	Error            string `json:"error"`
	ErrorDescription string `json:"error_description,omitempty"`
}

TokenError represents an OAuth 2.0 compliant error response

type TokenPair

type TokenPair struct {
	AccessToken  string `json:"access_token"`
	TokenType    string `json:"token_type"` // "Bearer"
	ExpiresIn    int64  `json:"expires_in"` // Seconds until access token expires
	RefreshToken string `json:"refresh_token,omitempty"`
	Scope        string `json:"scope,omitempty"`
}

TokenPair represents the response from a successful authentication

type TokenRequest

type TokenRequest struct {
	GrantType    string `json:"grant_type"`              // "password", "refresh_token", "client_credentials"
	Username     string `json:"username,omitempty"`      // For password grant
	Password     string `json:"password,omitempty"`      // For password grant
	RefreshToken string `json:"refresh_token,omitempty"` // For refresh_token grant
	Scope        string `json:"scope,omitempty"`         // Requested scopes
	ClientID     string `json:"client_id,omitempty"`     // Client identifier (for client_credentials, optional for others)
	ClientSecret string `json:"client_secret,omitempty"` // Client secret (for client_credentials via client_secret_post)
}

TokenRequest represents a request to the token endpoint

type TokenStore

type TokenStore interface {
	CreateToken(userID, email string, tokenType TokenType, expiryDuration time.Duration) (*AuthToken, error)
	GetToken(token string) (*AuthToken, error)
	DeleteToken(token string) error
	DeleteUserTokens(userID string, tokenType TokenType) error
}

TokenStore interface for managing auth tokens

type TokenType

type TokenType string

TokenType represents different types of auth tokens

const (
	TokenTypeEmailVerification TokenType = "email_verification"
	TokenTypePasswordReset     TokenType = "password_reset"
	TokenTypeRefresh           TokenType = "refresh"
)

type User

type User interface {
	Id() string
	Profile() map[string]any
}

User represents a unified user account

type UserStore

type UserStore interface {
	// CreateUser creates a new user with the given ID and profile
	CreateUser(userId string, isActive bool, profile map[string]any) (User, error)

	// GetUserById retrieves a user by their ID
	GetUserById(userId string) (User, error)

	// SaveUser creates or updates a user (upsert)
	SaveUser(user User) error
}

UserStore manages unified user accounts

type UsernameStore

type UsernameStore interface {
	// ReserveUsername reserves a username for a user (creates username -> userID mapping)
	// Returns error if username is already taken
	ReserveUsername(username string, userID string) error

	// GetUserByUsername looks up a userID by username
	// Returns error if username not found
	GetUserByUsername(username string) (userID string, err error)

	// ReleaseUsername removes a username reservation
	ReleaseUsername(username string) error

	// ChangeUsername atomically changes a username (release old, reserve new)
	// Returns error if new username is already taken
	ChangeUsername(oldUsername, newUsername, userID string) error
}

UsernameStore manages username uniqueness (optional - for apps that need username-based login)

Jump to

Keyboard shortcuts

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