localauth

package
v0.1.31 Latest Latest
Warning

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

Go to latest
Published: Jun 18, 2026 License: Apache-2.0 Imports: 14 Imported by: 1

Documentation

Index

Constants

View Source
const (
	VerificationExpiryEmail         = 24 * time.Hour
	VerificationExpiryPasswordReset = 1 * time.Hour
)

Default verification token expiry durations.

Variables

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 DetectUsernameType added in v0.1.0

func DetectUsernameType(username string) string

DetectUsernameType is re-exported from accounts so callers that import localauth don't need a second import for this widely-used helper.

func LinkLocalCredentials

func LinkLocalCredentials(config LinkLocalCredentialsConfig, userID string, username, password, email string) error

LinkLocalCredentials adds local (password) authentication to an existing OAuth-only user.

Types

type ConsoleEmailSender added in v0.1.0

type ConsoleEmailSender struct{}

ConsoleEmailSender is a development implementation that logs emails to console.

func (*ConsoleEmailSender) SendPasswordResetEmail added in v0.1.0

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

func (*ConsoleEmailSender) SendVerificationEmail added in v0.1.0

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

type CreateUserFunc added in v0.1.0

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

CreateUserFunc creates a new user with the given credentials.

func NewCreateUserFunc

func NewCreateUserFunc(userStore accounts.UserStore, identityStore accounts.IdentityStore, channelStore accounts.ChannelStore) CreateUserFunc

NewCreateUserFunc creates a CreateUserFunc from stores.

type CreateVerificationTokenRequest added in v0.1.7

type CreateVerificationTokenRequest struct {
	Subject        string
	Email          string
	Type           VerificationType
	ExpiryDuration time.Duration
}

CreateVerificationTokenRequest carries the inputs for issuing a verification token. Subject may be empty for password-reset flows where the AS does not want to reveal whether the email belongs to a registered user.

type CreateVerificationTokenResponse added in v0.1.7

type CreateVerificationTokenResponse struct {
	Token *VerificationToken
}

type Credentials added in v0.1.0

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 added in v0.1.0

type CredentialsValidator = accounts.CredentialsValidator

CredentialsValidator is the same shape as accounts.CredentialsValidator — type-aliased here so existing localauth callers don't have to switch imports.

func NewCredentialsValidator

func NewCredentialsValidator(identityStore accounts.IdentityStore, channelStore accounts.ChannelStore, userStore accounts.UserStore) CredentialsValidator

NewCredentialsValidator creates a CredentialsValidator from stores.

func NewCredentialsValidatorWithUsername

func NewCredentialsValidatorWithUsername(identityStore accounts.IdentityStore, channelStore accounts.ChannelStore, userStore accounts.UserStore, usernameStore accounts.UsernameStore) CredentialsValidator

NewCredentialsValidatorWithUsername creates a CredentialsValidator that supports logging in with username (in addition to email/phone).

type DeleteSubjectVerificationTokensRequest added in v0.1.7

type DeleteSubjectVerificationTokensRequest struct {
	Subject string
	Type    VerificationType
}

type DeleteSubjectVerificationTokensResponse added in v0.1.7

type DeleteSubjectVerificationTokensResponse struct{}

type DeleteVerificationTokenRequest added in v0.1.7

type DeleteVerificationTokenRequest struct {
	Token string
}

type DeleteVerificationTokenResponse added in v0.1.7

type DeleteVerificationTokenResponse struct{}

type GetLoggedInUserFunc

type GetLoggedInUserFunc func(r *http.Request) (userID string, err error)

GetLoggedInUserFunc returns the currently logged-in user ID from the request. Apps must implement this based on their session/JWT handling.

type GetVerificationTokenRequest added in v0.1.7

type GetVerificationTokenRequest struct {
	Token string
}

type GetVerificationTokenResponse added in v0.1.7

type GetVerificationTokenResponse struct {
	Token *VerificationToken
}

type LinkCredentialsConfig

type LinkCredentialsConfig struct {
	UserStore     accounts.UserStore
	IdentityStore accounts.IdentityStore
	ChannelStore  accounts.ChannelStore
	UsernameStore accounts.UsernameStore // Optional
}

LinkCredentialsConfig holds configuration for HandleLinkCredentials.

type LinkLocalCredentialsConfig added in v0.1.0

type LinkLocalCredentialsConfig struct {
	UserStore     accounts.UserStore
	IdentityStore accounts.IdentityStore
	ChannelStore  accounts.ChannelStore
	UsernameStore accounts.UsernameStore
}

LinkLocalCredentialsConfig groups the stores LinkLocalCredentials needs.

type LocalAuth

type LocalAuth struct {
	// Validates credentials during login
	ValidateCredentials CredentialsValidator

	// Validates credentials during signup (deprecated: use SignupPolicy instead)
	ValidateSignup SignupValidator

	// Creates a new user (for signup)
	CreateUser CreateUserFunc

	// Optional email sender for verification emails
	EmailSender SendEmail

	// Optional token store for email verification and password reset
	TokenStore VerificationTokenStore

	// Base URL for generating verification/reset links
	BaseURL string

	// Whether email verification is required before login
	RequireEmailVerification bool

	// Provider name (defaults to "local")
	Provider string

	// Form field names
	UsernameField string
	PasswordField string
	EmailField    string
	PhoneField    string

	// Handler called after successful authentication
	HandleUser accounts.HandleUserFunc

	// Callback to verify email by token
	VerifyEmail VerifyEmailFunc

	// Callback to update password
	UpdatePassword UpdatePasswordFunc

	// SignupPolicy defines what is required for signup (overrides ValidateSignup if set)
	SignupPolicy *SignupPolicy

	// OnSignupError is called when signup fails. If nil, returns JSON error.
	OnSignupError accounts.AuthErrorHandler

	// OnLoginError is called when login fails. If nil, returns JSON error.
	OnLoginError accounts.AuthErrorHandler

	// SignupURL is used for redirects on error (if OnSignupError uses redirects)
	SignupURL string

	// LoginURL is used for redirects on error (if OnLoginError uses redirects)
	LoginURL string

	// Optional UsernameStore for enforcing username uniqueness
	UsernameStore accounts.UsernameStore

	// ForgotPasswordURL: if set, GET /forgot-password redirects here and
	// POST /forgot-password redirects here with ?sent=true on success.
	// If empty, GET renders a basic HTML form and POST returns JSON.
	ForgotPasswordURL string

	// ResetPasswordURL: if set, GET /reset-password redirects here (with ?token=...)
	// and POST redirects here with ?success=true on success or ?error=... on failure.
	// If empty, GET renders a basic HTML form and POST returns JSON.
	ResetPasswordURL string

	// RateLimiter limits login attempts per key (IP:username). Optional.
	// When set, rate-limited requests receive 429 Too Many Requests.
	RateLimiter core.RateLimiter

	// Lockout locks accounts after consecutive failed login attempts. Optional.
	// When set, locked accounts receive 429 Too Many Requests until the lockout expires.
	Lockout *core.AccountLockout
}

Allows local username/password based authentication.

func (*LocalAuth) HandleForgotPassword

func (a *LocalAuth) HandleForgotPassword(w http.ResponseWriter, r *http.Request)

HandleForgotPassword handles forgot password requests (POST)

func (*LocalAuth) HandleForgotPasswordForm

func (a *LocalAuth) HandleForgotPasswordForm(w http.ResponseWriter, r *http.Request)

HandleForgotPasswordForm shows the forgot password form (GET)

func (*LocalAuth) HandleLinkCredentials

func (a *LocalAuth) HandleLinkCredentials(config LinkCredentialsConfig, getUser GetLoggedInUserFunc) http.HandlerFunc

HandleLinkCredentials returns an HTTP handler that adds local (password) auth to an existing OAuth-only user.

Who Calls This

Mount this handler at a protected route (requires login) like POST /auth/link-credentials:

localAuth := &oneauth.LocalAuth{...}
linkConfig := oneauth.LinkCredentialsConfig{
    UserStore:     stores.UserStore,
    IdentityStore: stores.IdentityStore,
    ChannelStore:  stores.ChannelStore,
    UsernameStore: stores.UsernameStore, // optional
}
getUser := func(r *http.Request) (string, error) {
    return getLoggedInUserIDFromSession(r), nil
}
mux.Handle("POST /auth/link-credentials", localAuth.HandleLinkCredentials(linkConfig, getUser))

Flow

  1. OAuth-only user visits profile page, sees "Add password" form
  2. User submits form with password (and optionally username)
  3. Handler validates input, creates local channel, reserves username
  4. User can now login with email/password OR their OAuth provider

Form Fields

  • password (required): The new password
  • username (optional): Username for login (if UsernameStore configured)

Responses

  • 200 OK: {"success": true, "message": "..."}
  • 400 Bad Request: {"error": "...", "code": "...", "field": "..."}
  • 401 Unauthorized: User not logged in
  • 409 Conflict: Local credentials already exist

func (*LocalAuth) HandleResetPassword

func (a *LocalAuth) HandleResetPassword(w http.ResponseWriter, r *http.Request)

HandleResetPassword handles password reset submissions (POST)

func (*LocalAuth) HandleResetPasswordForm

func (a *LocalAuth) HandleResetPasswordForm(w http.ResponseWriter, r *http.Request)

HandleResetPasswordForm shows the reset password form (GET)

func (*LocalAuth) HandleSignup

func (a *LocalAuth) HandleSignup(w http.ResponseWriter, r *http.Request)

HandleSignup processes user registration.

func (*LocalAuth) HandleVerifyEmail

func (a *LocalAuth) HandleVerifyEmail(w http.ResponseWriter, r *http.Request)

HandleVerifyEmail handles email verification via token

func (*LocalAuth) ServeHTTP

func (a *LocalAuth) ServeHTTP(w http.ResponseWriter, r *http.Request)

ServeHTTP handles login requests

type SendEmail added in v0.1.0

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

SendEmail lets applications provide their own email-sending implementation for localauth's verification-email and password-reset flows.

type SignupPolicy added in v0.1.0

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 added in v0.1.0

func DefaultSignupPolicy() SignupPolicy

DefaultSignupPolicy returns a sensible default signup policy.

func (SignupPolicy) GetMinPasswordLength added in v0.1.0

func (p SignupPolicy) GetMinPasswordLength() int

GetMinPasswordLength returns the minimum password length.

func (SignupPolicy) GetUsernamePattern added in v0.1.0

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

GetUsernamePattern returns the compiled username regex pattern.

type SignupValidator added in v0.1.0

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 UpdatePasswordFunc

type UpdatePasswordFunc func(email, newPassword string) error

func NewUpdatePasswordFunc

func NewUpdatePasswordFunc(identityStore accounts.IdentityStore, channelStore accounts.ChannelStore) UpdatePasswordFunc

NewUpdatePasswordFunc creates an UpdatePasswordFunc from stores.

type VerificationToken added in v0.1.0

type VerificationToken struct {
	Token     string           `json:"token"`
	Type      VerificationType `json:"type"`
	Subject   string           `json:"subject"`
	Email     string           `json:"email"`
	CreatedAt time.Time        `json:"created_at"`
	ExpiresAt time.Time        `json:"expires_at"`
}

VerificationToken represents a short-lived email-mediated token used by localauth flows (email verification, password reset).

Renamed from the previous core.AuthToken so the type name reflects its role and doesn't collide with OAuth access/refresh tokens.

func (*VerificationToken) IsExpired added in v0.1.0

func (t *VerificationToken) IsExpired() bool

IsExpired checks if a verification token has expired.

func (*VerificationToken) IsValid added in v0.1.0

func (t *VerificationToken) IsValid(expectedType VerificationType) bool

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

type VerificationTokenStore added in v0.1.0

VerificationTokenStore manages localauth verification tokens (signup email-verify, password-reset). Renamed from core.TokenStore.

type VerificationType added in v0.1.0

type VerificationType string

VerificationType is the kind of email/phone-mediated verification token issued by localauth (e.g. signup email-verify, password-reset).

Renamed from the previous core.TokenType to avoid colliding with OAuth access/refresh-token semantics that live in apiauth/core.

const (
	// String values kept stable for backwards-compatible persisted data
	// across the rename.
	VerificationTypeEmail         VerificationType = "email_verification"
	VerificationTypePasswordReset VerificationType = "password_reset"
)

type VerifyEmailFunc

type VerifyEmailFunc func(token string) error

func NewVerifyEmailFunc

func NewVerifyEmailFunc(identityStore accounts.IdentityStore, tokenStore VerificationTokenStore) VerifyEmailFunc

NewVerifyEmailFunc creates a VerifyEmailFunc from stores.

Jump to

Keyboard shortcuts

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