goAuth

package module
v0.1.1 Latest Latest
Warning

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

Go to latest
Published: Feb 19, 2026 License: Apache-2.0 Imports: 27 Imported by: 0

README

goAuth

Low-latency authentication engine for Go: JWT access tokens + Redis-backed sessions + rotating refresh tokens + bitmask RBAC.

Go Tests Go Version Race Detector


Features

  • Three validation modes — JWT-only (0 Redis ops), Hybrid, Strict (instant revocation)
  • Refresh token rotation — atomic Lua CAS with replay detection
  • MFA — TOTP (RFC 6238) + backup codes with rate limiting
  • Password management — Argon2id hashing, reset (Token/OTP/UUID strategies), change with reuse detection
  • Email verification — enumeration-resistant with Lua CAS consumption
  • Permission system — 64/128/256/512-bit frozen bitmasks, O(1) checks
  • Rate limiting — 7-domain fixed-window limiters + auto-lockout
  • Device binding — IP/UA fingerprint enforcement or anomaly detection
  • Audit + Metrics — 44 counters, latency histogram, Prometheus + OpenTelemetry exporters
  • Multi-tenancy — tenant-scoped sessions, counters, and rate limits

Quickstart

package main

import (
    "context"
    "fmt"
    "log"

    goAuth "github.com/MrEthical07/goAuth"
    "github.com/redis/go-redis/v9"
)

func main() {
    rdb := redis.NewClient(&redis.Options{Addr: "127.0.0.1:6379"})

    engine, err := goAuth.New().
        WithRedis(rdb).
        WithPermissions([]string{"user.read", "user.write"}).
        WithRoles(map[string][]string{
            "admin": {"user.read", "user.write"},
        }).
        WithUserProvider(myProvider{}).
        Build()
    if err != nil {
        log.Fatal(err)
    }
    defer engine.Close()

    // Login
    access, refresh, err := engine.Login(context.Background(), "[email protected]", "password")
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println("Access:", access[:20]+"...")

    // Validate
    result, err := engine.ValidateAccess(context.Background(), access)
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println("UserID:", result.UserID)

    // Refresh
    newAccess, newRefresh, err := engine.Refresh(context.Background(), refresh)
    _ = newAccess
    _ = newRefresh
}

See examples/http-minimal for a complete HTTP server with login, refresh, logout, and protected routes.

Installation

go get github.com/MrEthical07/goAuth

Requirements: Go 1.24+, Redis 6+

Validation Modes

Mode Redis Ops Use Case
ModeJWTOnly 0 Stateless microservices, dashboards
ModeHybrid 0–1 Most applications (default)
ModeStrict 1 Financial, healthcare, compliance
// Per-route mode with middleware
mux.Handle("/api/read", middleware.RequireJWTOnly(engine)(readHandler))
mux.Handle("/api/admin", middleware.RequireStrict(engine)(adminHandler))

Configuration

// Start from a preset
cfg := goAuth.HighSecurityConfig()
cfg.JWT.AccessTTL = 3 * time.Minute

// Lint for misconfigurations
if err := cfg.Lint().AsError(goAuth.LintHigh); err != nil {
    log.Fatal(err)
}

Three presets: DefaultConfig(), HighSecurityConfig(), HighThroughputConfig(). See docs/config.md.

Documentation

Document Description
docs/index.md Documentation hub
docs/flows.md All auth flows with step lists
docs/api-reference.md Full API reference
docs/architecture.md System design
docs/security.md Threat model and mitigations
docs/performance.md Benchmarks and budgets
docs/ops.md Deployment and monitoring
docs/config.md Configuration reference
docs/roadmap.md Future plans
CHANGELOG.md Release history
Root-Level Documents
File Purpose
CHANGELOG.md Release history — follows Keep a Changelog format with Semantic Versioning
CONTRIBUTING.md Contribution guidelines — conventions for docs, code, testing, and changelog entries
docsAuditReport.md Documentation hardening audit — tracks doc coverage, accuracy, and consistency across all features
featureReport.md Full feature verification report — all 21 features + 4 NFRs with test evidence and benchmarks

Testing

# All tests
go test ./...

# With race detector
go test -race ./...

# Integration tests (requires Redis)
docker compose -f docker-compose.test.yml up -d
go test -tags=integration ./test/...

# Benchmarks
go test -run '^$' -bench . -benchmem ./...

266 tests, 4 fuzz targets, 13 benchmarks. Race-detector clean.

License

Licensed under the Apache License, Version 2.0. See LICENSE and NOTICE.


Note: AI agents were used for documentation and report generation in this project. Content has been verified against actual test outputs and code, but please exercise caution — review carefully and report any issues in the Issues tab.

Documentation

Overview

Package goAuth provides a low-latency authentication engine with JWT access tokens, rotating opaque refresh tokens, Redis-backed session controls, and bitmask-based RBAC.

The package is designed for concurrent server workloads: Engine methods are safe to call from multiple goroutines after initialization through Builder.Build.

Architecture boundaries

goAuth is the public surface. It exposes Engine, Builder, Config, and value types (MetricsSnapshot, SessionInfo, etc.). All internal coordination — flow orchestration, session encoding, rate limiting, audit dispatch — lives under internal/ and is never exported.

What this package must NOT do

  • Expose Redis clients, internal stores, or encoding details in its public API.
  • Perform I/O outside of Engine methods (construction via Builder is allocation-only until Build).
  • Import any sub-package that re-imports goAuth (no import cycles).

Performance contract

Validate is the hot path. It must not allocate beyond the returned Claims struct and must complete without Redis round-trips in ModeJWTOnly. Refresh, Login, and account operations are allowed one Redis round-trip per call.

Index

Constants

View Source
const (
	// MetricLoginSuccess is an exported constant or variable used by the authentication engine.
	MetricLoginSuccess = MetricID(internalmetrics.MetricLoginSuccess)
	// MetricLoginFailure is an exported constant or variable used by the authentication engine.
	MetricLoginFailure = MetricID(internalmetrics.MetricLoginFailure)
	// MetricLoginRateLimited is an exported constant or variable used by the authentication engine.
	MetricLoginRateLimited = MetricID(internalmetrics.MetricLoginRateLimited)
	// MetricRefreshSuccess is an exported constant or variable used by the authentication engine.
	MetricRefreshSuccess = MetricID(internalmetrics.MetricRefreshSuccess)
	// MetricRefreshFailure is an exported constant or variable used by the authentication engine.
	MetricRefreshFailure = MetricID(internalmetrics.MetricRefreshFailure)
	// MetricRefreshReuseDetected is an exported constant or variable used by the authentication engine.
	MetricRefreshReuseDetected = MetricID(internalmetrics.MetricRefreshReuseDetected)
	// MetricReplayDetected is an exported constant or variable used by the authentication engine.
	MetricReplayDetected = MetricID(internalmetrics.MetricReplayDetected)
	// MetricRefreshRateLimited is an exported constant or variable used by the authentication engine.
	MetricRefreshRateLimited = MetricID(internalmetrics.MetricRefreshRateLimited)
	// MetricDeviceIPMismatch is an exported constant or variable used by the authentication engine.
	MetricDeviceIPMismatch = MetricID(internalmetrics.MetricDeviceIPMismatch)
	// MetricDeviceUAMismatch is an exported constant or variable used by the authentication engine.
	MetricDeviceUAMismatch = MetricID(internalmetrics.MetricDeviceUAMismatch)
	// MetricDeviceRejected is an exported constant or variable used by the authentication engine.
	MetricDeviceRejected = MetricID(internalmetrics.MetricDeviceRejected)
	// MetricTOTPRequired is an exported constant or variable used by the authentication engine.
	MetricTOTPRequired = MetricID(internalmetrics.MetricTOTPRequired)
	// MetricTOTPFailure is an exported constant or variable used by the authentication engine.
	MetricTOTPFailure = MetricID(internalmetrics.MetricTOTPFailure)
	// MetricTOTPSuccess is an exported constant or variable used by the authentication engine.
	MetricTOTPSuccess = MetricID(internalmetrics.MetricTOTPSuccess)
	// MetricMFALoginRequired is an exported constant or variable used by the authentication engine.
	MetricMFALoginRequired = MetricID(internalmetrics.MetricMFALoginRequired)
	// MetricMFALoginSuccess is an exported constant or variable used by the authentication engine.
	MetricMFALoginSuccess = MetricID(internalmetrics.MetricMFALoginSuccess)
	// MetricMFALoginFailure is an exported constant or variable used by the authentication engine.
	MetricMFALoginFailure = MetricID(internalmetrics.MetricMFALoginFailure)
	// MetricMFAReplayAttempt is an exported constant or variable used by the authentication engine.
	MetricMFAReplayAttempt = MetricID(internalmetrics.MetricMFAReplayAttempt)
	// MetricBackupCodeUsed is an exported constant or variable used by the authentication engine.
	MetricBackupCodeUsed = MetricID(internalmetrics.MetricBackupCodeUsed)
	// MetricBackupCodeFailed is an exported constant or variable used by the authentication engine.
	MetricBackupCodeFailed = MetricID(internalmetrics.MetricBackupCodeFailed)
	// MetricBackupCodeRegenerated is an exported constant or variable used by the authentication engine.
	MetricBackupCodeRegenerated = MetricID(internalmetrics.MetricBackupCodeRegenerated)
	// MetricRateLimitHit is an exported constant or variable used by the authentication engine.
	MetricRateLimitHit = MetricID(internalmetrics.MetricRateLimitHit)
	// MetricSessionCreated is an exported constant or variable used by the authentication engine.
	MetricSessionCreated = MetricID(internalmetrics.MetricSessionCreated)
	// MetricSessionInvalidated is an exported constant or variable used by the authentication engine.
	MetricSessionInvalidated = MetricID(internalmetrics.MetricSessionInvalidated)
	// MetricLogout is an exported constant or variable used by the authentication engine.
	MetricLogout = MetricID(internalmetrics.MetricLogout)
	// MetricLogoutAll is an exported constant or variable used by the authentication engine.
	MetricLogoutAll = MetricID(internalmetrics.MetricLogoutAll)
	// MetricAccountCreationSuccess is an exported constant or variable used by the authentication engine.
	MetricAccountCreationSuccess = MetricID(internalmetrics.MetricAccountCreationSuccess)
	// MetricAccountCreationDuplicate is an exported constant or variable used by the authentication engine.
	MetricAccountCreationDuplicate = MetricID(internalmetrics.MetricAccountCreationDuplicate)
	// MetricAccountCreationRateLimited is an exported constant or variable used by the authentication engine.
	MetricAccountCreationRateLimited = MetricID(internalmetrics.MetricAccountCreationRateLimited)
	// MetricPasswordChangeSuccess is an exported constant or variable used by the authentication engine.
	MetricPasswordChangeSuccess = MetricID(internalmetrics.MetricPasswordChangeSuccess)
	// MetricPasswordChangeInvalidOld is an exported constant or variable used by the authentication engine.
	MetricPasswordChangeInvalidOld = MetricID(internalmetrics.MetricPasswordChangeInvalidOld)
	// MetricPasswordChangeReuseRejected is an exported constant or variable used by the authentication engine.
	MetricPasswordChangeReuseRejected = MetricID(internalmetrics.MetricPasswordChangeReuseRejected)
	// MetricPasswordResetRequest is an exported constant or variable used by the authentication engine.
	MetricPasswordResetRequest = MetricID(internalmetrics.MetricPasswordResetRequest)
	// MetricPasswordResetConfirmSuccess is an exported constant or variable used by the authentication engine.
	MetricPasswordResetConfirmSuccess = MetricID(internalmetrics.MetricPasswordResetConfirmSuccess)
	// MetricPasswordResetConfirmFailure is an exported constant or variable used by the authentication engine.
	MetricPasswordResetConfirmFailure = MetricID(internalmetrics.MetricPasswordResetConfirmFailure)
	// MetricPasswordResetAttemptsExceeded is an exported constant or variable used by the authentication engine.
	MetricPasswordResetAttemptsExceeded = MetricID(internalmetrics.MetricPasswordResetAttemptsExceeded)
	// MetricEmailVerificationRequest is an exported constant or variable used by the authentication engine.
	MetricEmailVerificationRequest = MetricID(internalmetrics.MetricEmailVerificationRequest)
	// MetricEmailVerificationSuccess is an exported constant or variable used by the authentication engine.
	MetricEmailVerificationSuccess = MetricID(internalmetrics.MetricEmailVerificationSuccess)
	// MetricEmailVerificationFailure is an exported constant or variable used by the authentication engine.
	MetricEmailVerificationFailure = MetricID(internalmetrics.MetricEmailVerificationFailure)
	// MetricEmailVerificationAttemptsExceeded is an exported constant or variable used by the authentication engine.
	MetricEmailVerificationAttemptsExceeded = MetricID(internalmetrics.MetricEmailVerificationAttemptsExceeded)
	// MetricAccountDisabled is an exported constant or variable used by the authentication engine.
	MetricAccountDisabled = MetricID(internalmetrics.MetricAccountDisabled)
	// MetricAccountLocked is an exported constant or variable used by the authentication engine.
	MetricAccountLocked = MetricID(internalmetrics.MetricAccountLocked)
	// MetricAccountDeleted is an exported constant or variable used by the authentication engine.
	MetricAccountDeleted = MetricID(internalmetrics.MetricAccountDeleted)
	// MetricValidateLatency is an exported constant or variable used by the authentication engine.
	MetricValidateLatency = MetricID(internalmetrics.MetricValidateLatency)
)

Variables

View Source
var (
	// ErrUnauthorized is an exported constant or variable used by the authentication engine.
	ErrUnauthorized = errors.New("unauthorized")
	// ErrInvalidCredentials is an exported constant or variable used by the authentication engine.
	ErrInvalidCredentials = errors.New("invalid credentials")
	// ErrUserNotFound is an exported constant or variable used by the authentication engine.
	ErrUserNotFound = errors.New("user not found")
	// ErrLoginRateLimited is an exported constant or variable used by the authentication engine.
	ErrLoginRateLimited = errors.New("login rate limited")
	// ErrRefreshRateLimited is an exported constant or variable used by the authentication engine.
	ErrRefreshRateLimited = errors.New("refresh rate limited")
	// ErrAccountExists is an exported constant or variable used by the authentication engine.
	ErrAccountExists = errors.New("account already exists")
	// ErrAccountCreationDisabled is an exported constant or variable used by the authentication engine.
	ErrAccountCreationDisabled = errors.New("account creation disabled")
	// ErrAccountCreationRateLimited is an exported constant or variable used by the authentication engine.
	ErrAccountCreationRateLimited = errors.New("account creation rate limited")
	// ErrAccountCreationUnavailable is an exported constant or variable used by the authentication engine.
	ErrAccountCreationUnavailable = errors.New("account creation backend unavailable")
	// ErrAccountCreationInvalid is an exported constant or variable used by the authentication engine.
	ErrAccountCreationInvalid = errors.New("invalid account creation request")
	// ErrAccountRoleInvalid is an exported constant or variable used by the authentication engine.
	ErrAccountRoleInvalid = errors.New("invalid account role")
	// ErrAccountUnverified is an exported constant or variable used by the authentication engine.
	ErrAccountUnverified = errors.New("account unverified")
	// ErrAccountDisabled is an exported constant or variable used by the authentication engine.
	ErrAccountDisabled = errors.New("account disabled")
	// ErrAccountLocked is an exported constant or variable used by the authentication engine.
	ErrAccountLocked = errors.New("account locked")
	// ErrAccountDeleted is an exported constant or variable used by the authentication engine.
	ErrAccountDeleted = errors.New("account deleted")
	// ErrAccountVersionNotAdvanced is an exported constant or variable used by the authentication engine.
	ErrAccountVersionNotAdvanced = errors.New("account version not advanced on status change")
	// ErrEmailVerificationDisabled is an exported constant or variable used by the authentication engine.
	ErrEmailVerificationDisabled = errors.New("email verification disabled")
	// ErrEmailVerificationInvalid is an exported constant or variable used by the authentication engine.
	ErrEmailVerificationInvalid = errors.New("email verification challenge invalid")
	// ErrEmailVerificationRateLimited is an exported constant or variable used by the authentication engine.
	ErrEmailVerificationRateLimited = errors.New("email verification rate limited")
	// ErrEmailVerificationUnavailable is an exported constant or variable used by the authentication engine.
	ErrEmailVerificationUnavailable = errors.New("email verification backend unavailable")
	// ErrEmailVerificationAttempts is an exported constant or variable used by the authentication engine.
	ErrEmailVerificationAttempts = errors.New("email verification attempts exceeded")
	// ErrPasswordResetDisabled is an exported constant or variable used by the authentication engine.
	ErrPasswordResetDisabled = errors.New("password reset disabled")
	// ErrPasswordResetInvalid is an exported constant or variable used by the authentication engine.
	ErrPasswordResetInvalid = errors.New("password reset challenge invalid")
	// ErrPasswordResetRateLimited is an exported constant or variable used by the authentication engine.
	ErrPasswordResetRateLimited = errors.New("password reset rate limited")
	// ErrPasswordResetUnavailable is an exported constant or variable used by the authentication engine.
	ErrPasswordResetUnavailable = errors.New("password reset backend unavailable")
	// ErrPasswordResetAttempts is an exported constant or variable used by the authentication engine.
	ErrPasswordResetAttempts = errors.New("password reset attempts exceeded")
	// ErrPasswordPolicy is an exported constant or variable used by the authentication engine.
	ErrPasswordPolicy = errors.New("password policy violation")
	// ErrPasswordReuse is an exported constant or variable used by the authentication engine.
	ErrPasswordReuse = errors.New("new password must be different from current password")
	// ErrSessionCreationFailed is an exported constant or variable used by the authentication engine.
	ErrSessionCreationFailed = errors.New("session creation failed")
	// ErrSessionInvalidationFailed is an exported constant or variable used by the authentication engine.
	ErrSessionInvalidationFailed = errors.New("session invalidation failed")
	// ErrSessionLimitExceeded is an exported constant or variable used by the authentication engine.
	ErrSessionLimitExceeded = errors.New("session limit exceeded")
	// ErrTenantSessionLimitExceeded is an exported constant or variable used by the authentication engine.
	ErrTenantSessionLimitExceeded = errors.New("tenant session limit exceeded")
	// ErrDeviceBindingRejected is an exported constant or variable used by the authentication engine.
	ErrDeviceBindingRejected = errors.New("device binding rejected")
	// ErrTOTPFeatureDisabled is an exported constant or variable used by the authentication engine.
	ErrTOTPFeatureDisabled = errors.New("totp feature disabled")
	// ErrTOTPRequired is an exported constant or variable used by the authentication engine.
	ErrTOTPRequired = errors.New("totp required")
	// ErrTOTPInvalid is an exported constant or variable used by the authentication engine.
	ErrTOTPInvalid = errors.New("invalid totp code")
	// ErrTOTPRateLimited is an exported constant or variable used by the authentication engine.
	ErrTOTPRateLimited = errors.New("totp attempts rate limited")
	// ErrTOTPNotConfigured is an exported constant or variable used by the authentication engine.
	ErrTOTPNotConfigured = errors.New("totp not configured")
	// ErrTOTPUnavailable is an exported constant or variable used by the authentication engine.
	ErrTOTPUnavailable = errors.New("totp backend unavailable")
	// ErrMFALoginRequired is an exported constant or variable used by the authentication engine.
	ErrMFALoginRequired = errors.New("mfa required")
	// ErrMFALoginInvalid is an exported constant or variable used by the authentication engine.
	ErrMFALoginInvalid = errors.New("mfa challenge invalid")
	// ErrMFALoginExpired is an exported constant or variable used by the authentication engine.
	ErrMFALoginExpired = errors.New("mfa challenge expired")
	// ErrMFALoginAttemptsExceeded is an exported constant or variable used by the authentication engine.
	ErrMFALoginAttemptsExceeded = errors.New("mfa challenge attempts exceeded")
	// ErrMFALoginReplay is an exported constant or variable used by the authentication engine.
	ErrMFALoginReplay = errors.New("mfa challenge replay detected")
	// ErrMFALoginUnavailable is an exported constant or variable used by the authentication engine.
	ErrMFALoginUnavailable = errors.New("mfa challenge backend unavailable")
	// ErrBackupCodeInvalid is an exported constant or variable used by the authentication engine.
	ErrBackupCodeInvalid = errors.New("invalid backup code")
	// ErrBackupCodeRateLimited is an exported constant or variable used by the authentication engine.
	ErrBackupCodeRateLimited = errors.New("backup code rate limited")
	// ErrBackupCodeUnavailable is an exported constant or variable used by the authentication engine.
	ErrBackupCodeUnavailable = errors.New("backup code backend unavailable")
	// ErrBackupCodesNotConfigured is an exported constant or variable used by the authentication engine.
	ErrBackupCodesNotConfigured = errors.New("backup codes not configured")
	// ErrBackupCodeRegenerationRequiresTOTP is an exported constant or variable used by the authentication engine.
	ErrBackupCodeRegenerationRequiresTOTP = errors.New("backup code regeneration requires totp verification")
	// ErrSessionNotFound is an exported constant or variable used by the authentication engine.
	ErrSessionNotFound = errors.New("session not found")
	// ErrTokenInvalid is an exported constant or variable used by the authentication engine.
	ErrTokenInvalid = errors.New("invalid token")
	// ErrTokenClockSkew is an exported constant or variable used by the authentication engine.
	ErrTokenClockSkew = errors.New("token clock skew exceeded")
	// ErrInvalidRouteMode is an exported constant or variable used by the authentication engine.
	ErrInvalidRouteMode = errors.New("invalid route validation mode")
	// ErrStrictBackendDown is an exported constant or variable used by the authentication engine.
	ErrStrictBackendDown = errors.New("strict validation backend unavailable")
	// ErrRefreshInvalid is an exported constant or variable used by the authentication engine.
	ErrRefreshInvalid = errors.New("invalid refresh token")
	// ErrRefreshReuse is an exported constant or variable used by the authentication engine.
	ErrRefreshReuse = errors.New("refresh token reuse detected")
	// ErrPermissionDenied is an exported constant or variable used by the authentication engine.
	ErrPermissionDenied = errors.New("permission denied")
	// ErrEngineNotReady is an exported constant or variable used by the authentication engine.
	ErrEngineNotReady = errors.New("engine not initialized")
	// ErrProviderDuplicateIdentifier is an exported constant or variable used by the authentication engine.
	ErrProviderDuplicateIdentifier = errors.New("provider duplicate identifier")
)

Functions

func WithClientIP

func WithClientIP(ctx context.Context, ip string) context.Context

WithClientIP attaches the caller’s IP address to ctx. The Engine uses it for per-IP rate limiting, audit logging, and device binding checks.

Docs: docs/rate_limiting.md, docs/device_binding.md

func WithTenantID

func WithTenantID(ctx context.Context, tenantID string) context.Context

WithTenantID attaches a tenant identifier to ctx for multi-tenant session isolation. When multi-tenancy is disabled, the default tenant "0" is used.

Docs: docs/session.md, docs/engine.md

func WithUserAgent

func WithUserAgent(ctx context.Context, userAgent string) context.Context

WithUserAgent attaches the HTTP User-Agent string to ctx. Used by the device binding subsystem to detect session hijacking.

Docs: docs/device_binding.md

Types

type AccountConfig

type AccountConfig struct {
	Enabled                               bool
	AutoLogin                             bool
	EnableIPThrottle                      bool
	EnableIdentifierThrottle              bool
	AccountCreationMaxAttempts            int
	AccountCreationCooldown               time.Duration
	DefaultRole                           string
	AllowDuplicateIdentifierAcrossTenants bool
}

AccountConfig controls account creation, auto-login, default role, and rate limiting.

Docs: docs/config.md

type AccountStatus

type AccountStatus uint8

AccountStatus represents the lifecycle state of a user account.

Docs: docs/functionality-account-status.md
const (
	// AccountActive is an exported constant or variable used by the authentication engine.
	AccountActive AccountStatus = iota
	// AccountPendingVerification is an exported constant or variable used by the authentication engine.
	AccountPendingVerification
	// AccountDisabled is an exported constant or variable used by the authentication engine.
	AccountDisabled
	// AccountLocked is an exported constant or variable used by the authentication engine.
	AccountLocked
	// AccountDeleted is an exported constant or variable used by the authentication engine.
	AccountDeleted

	// StatusPendingVerification is an exported constant or variable used by the authentication engine.
	StatusPendingVerification = AccountPendingVerification
)

type AuditConfig

type AuditConfig struct {
	Enabled    bool
	BufferSize int
	DropIfFull bool
}

AuditConfig controls the audit event dispatcher: enable/disable, buffer size, and overflow policy.

Docs: docs/audit.md, docs/config.md

type AuditErrorCode

type AuditErrorCode string

AuditErrorCode defines a public type used by goAuth APIs.

AuditErrorCode instances are intended to be configured during initialization and then treated as immutable unless documented otherwise.

type AuditEvent

type AuditEvent = internalaudit.Event

AuditEvent is a structured audit record emitted by the engine.

Docs: docs/audit.md

type AuditSink

type AuditSink = internalaudit.Sink

AuditSink receives AuditEvent values from the engine’s audit dispatcher.

Docs: docs/audit.md

type AuthResult

type AuthResult struct {
	UserID   string
	TenantID string

	Role string

	Mask interface{}

	Permissions []string
}

AuthResult is returned by Engine.Validate and Engine.ValidateAccess. It contains the authenticated user’s ID, tenant, role, decoded permission mask, and optionally the permission name list.

Docs: docs/jwt.md, docs/permission.md

type BackupCodeRecord

type BackupCodeRecord struct {
	Hash [32]byte
}

BackupCodeRecord stores the SHA-256 hash of a single backup code. The plaintext is never persisted.

type Builder

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

Builder constructs an Engine through a fluent API. Call New to start, chain With* methods, then call Builder.Build to validate configuration and produce an immutable Engine. A Builder can only be built once.

Docs: docs/engine.md, docs/usage.md

func New

func New() *Builder

New creates a fresh Builder initialized with DefaultConfig.

Docs: docs/engine.md, docs/usage.md

func (*Builder) Build

func (b *Builder) Build() (*Engine, error)

Build validates the accumulated configuration, initializes every subsystem (JWT manager, session store, rate limiters, TOTP manager, password hasher, audit dispatcher, permission registry, role manager), and returns an immutable Engine ready for concurrent use.

Build may only be called once per Builder instance.

Docs: docs/engine.md, docs/config.md, docs/usage.md

func (*Builder) WithAuditSink

func (b *Builder) WithAuditSink(sink AuditSink) *Builder

WithAuditSink sets the AuditSink that receives structured audit events. Pass nil to disable audit dispatch.

Docs: docs/audit.md

func (*Builder) WithConfig

func (b *Builder) WithConfig(cfg Config) *Builder

WithConfig replaces the builder’s configuration. The provided Config is deep-copied; later mutations to the caller’s copy have no effect.

Docs: docs/config.md

func (*Builder) WithLatencyHistograms

func (b *Builder) WithLatencyHistograms(enabled bool) *Builder

WithLatencyHistograms enables per-operation latency histograms inside the metrics subsystem. Adds a small allocation overhead per tracked op.

Docs: docs/metrics.md

func (*Builder) WithMetricsEnabled

func (b *Builder) WithMetricsEnabled(enabled bool) *Builder

WithMetricsEnabled enables or disables the in-process metrics counters. When disabled, MetricsSnapshot returns zero values.

Docs: docs/metrics.md

func (*Builder) WithPermissions

func (b *Builder) WithPermissions(perms []string) *Builder

WithPermissions registers the permission names that will be mapped to bitmask bits. Order determines bit assignment.

Docs: docs/permission.md

func (*Builder) WithRedis

func (b *Builder) WithRedis(client redis.UniversalClient) *Builder

WithRedis sets the Redis client used for sessions, rate limiting, and all Redis-backed stores. Required for all validation modes.

Docs: docs/config.md, docs/session.md

func (*Builder) WithRoles

func (b *Builder) WithRoles(r map[string][]string) *Builder

WithRoles registers role names and their associated permission lists. Each role gets a pre-computed bitmask at build time.

Docs: docs/permission.md

func (*Builder) WithUserProvider

func (b *Builder) WithUserProvider(up UserProvider) *Builder

WithUserProvider sets the UserProvider implementation that the engine uses for credential lookup, account creation, TOTP storage, etc.

Docs: docs/engine.md

type CacheConfig

type CacheConfig struct {
	LRUEnabled bool
	Size       int
}

CacheConfig controls optional in-memory caching of session data.

type ChannelSink

type ChannelSink = internalaudit.ChannelSink

ChannelSink is a buffered channel-based AuditSink.

Docs: docs/audit.md

func NewChannelSink

func NewChannelSink(buffer int) *ChannelSink

NewChannelSink creates a ChannelSink with the given buffer capacity.

Docs: docs/audit.md

type Config

type Config struct {
	JWT               JWTConfig
	Session           SessionConfig
	SessionHardening  SessionHardeningConfig
	DeviceBinding     DeviceBindingConfig
	TOTP              TOTPConfig
	Password          PasswordConfig
	PasswordReset     PasswordResetConfig
	EmailVerification EmailVerificationConfig
	Account           AccountConfig
	Audit             AuditConfig
	Metrics           MetricsConfig
	Security          SecurityConfig
	MultiTenant       MultiTenantConfig
	Database          DatabaseConfig
	Permission        PermissionConfig
	Cache             CacheConfig
	Result            ResultConfig
	Logger            *slog.Logger
	ValidationMode    ValidationMode
}

Config is the top-level configuration struct for the goAuth Engine. It embeds sub-configs for JWT, sessions, passwords, MFA, rate limiting, audit, metrics, and more. Obtain defaults via DefaultConfig.

Docs: docs/config.md

func DefaultConfig

func DefaultConfig() Config

DefaultConfig returns a production-safe baseline preset.

The preset keeps hybrid validation, refresh rotation/reuse enforcement, and Ed25519 signing. It also generates an ephemeral signing keypair so the result validates without additional key wiring.

func HighSecurityConfig

func HighSecurityConfig() Config

HighSecurityConfig returns a strict preset for security-critical deployments.

This preset enables strict validation mode and tighter token/rate-limiter windows, and enforces iat presence.

func HighThroughputConfig

func HighThroughputConfig() Config

HighThroughputConfig returns a preset optimized for higher sustained request volume while keeping security defaults intact.

It keeps Hybrid validation as the global mode; callers can use per-route `ModeJWTOnly` where immediate revocation is not required.

func (*Config) Lint

func (c *Config) Lint() LintResult

Lint returns advisory warnings for configurations that are technically valid but potentially dangerous in production. Unlike Validate(), Lint() never rejects a config — it only surfaces things worth reviewing.

Each warning has a stable code and a severity level (INFO/WARN/HIGH). Use the returned LintResult helpers to filter or promote to errors:

for _, w := range cfg.Lint() {
    slog.Warn("config lint", "code", w.Code, "severity", w.Severity.String(), "msg", w.Message)
}

// Fail startup on HIGH severity:
if err := cfg.Lint().AsError(goAuth.LintHigh); err != nil {
    log.Fatalf("config lint: %v", err)
}

func (*Config) Validate

func (c *Config) Validate() error

Validate checks the Config for invalid or contradictory settings. It is called automatically by Builder.Build.

Docs: docs/config.md

type CreateAccountRequest

type CreateAccountRequest struct {
	Identifier string
	Password   string
	Role       string
}

CreateAccountRequest is the input for Engine.CreateAccount. Identifier and Password are required; Role defaults to [Config.Account.DefaultRole] when empty.

type CreateAccountResult

type CreateAccountResult struct {
	UserID       string
	Role         string
	AccessToken  string
	RefreshToken string
}

CreateAccountResult is returned by Engine.CreateAccount. It includes the new UserID and, when AutoLogin is enabled, access+refresh tokens.

type CreateUserInput

type CreateUserInput struct {
	Identifier        string
	PasswordHash      string
	Role              string
	TenantID          string
	Status            AccountStatus
	PermissionVersion uint32
	RoleVersion       uint32
	AccountVersion    uint32
}

CreateUserInput is the input for [UserProvider.CreateUser].

type DatabaseConfig

type DatabaseConfig struct {
	Address                   string
	Password                  string
	MaxConnections            int
	MinConnections            int
	ConnMaxLifetime           time.Duration
	PreparedStatementsEnabled bool
}

DatabaseConfig holds Redis connection parameters (currently unused; prefer Builder.WithRedis).

type DeviceBindingConfig

type DeviceBindingConfig struct {
	Enabled                 bool
	EnforceIPBinding        bool
	EnforceUserAgentBinding bool
	DetectIPChange          bool
	DetectUserAgentChange   bool
}

DeviceBindingConfig controls IP and User-Agent binding checks on session validation.

Docs: docs/device_binding.md, docs/config.md

type EmailVerificationConfig

type EmailVerificationConfig struct {
	Enabled                  bool
	Strategy                 VerificationStrategyType
	VerificationTTL          time.Duration
	MaxAttempts              int
	RequireForLogin          bool
	EnableIPThrottle         bool
	EnableIdentifierThrottle bool
	OTPDigits                int
}

EmailVerificationConfig controls the email verification flow.

Docs: docs/email_verification.md, docs/config.md

type Engine

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

Engine is the central authentication coordinator.

It holds references to every subsystem (JWT manager, session store, rate limiters, TOTP manager, audit dispatcher, etc.) and exposes the public operations: Login, Refresh, Validate, Logout, and account management. Build an Engine through Builder.Build; once built the Engine is safe for concurrent use and must not be reconfigured.

Docs: docs/engine.md, docs/architecture.md

func (*Engine) ActiveSessionEstimate

func (e *Engine) ActiveSessionEstimate(ctx context.Context) (int, error)

ActiveSessionEstimate returns an estimated total of active sessions across all tenants using a Redis SCAN-based count.

Flow:        Introspection
Docs:        docs/introspection.md
Performance: 1 SCAN (may be slow on large keyspaces).

func (*Engine) AuditDropped

func (e *Engine) AuditDropped() uint64

AuditDropped returns the total number of audit events that were dropped because the audit buffer was full and DropIfFull was enabled. Useful for monitoring back-pressure on the audit pipeline.

Docs: docs/audit.md
Performance: O(1) atomic load, no allocations, no Redis.

func (*Engine) ChangePassword

func (e *Engine) ChangePassword(ctx context.Context, userID, oldPassword, newPassword string) error

ChangePassword verifies the old password, hashes the new one, persists the updated hash via [UserProvider.UpdatePasswordHash], and invalidates all of the user’s sessions so they must re-authenticate. The login rate limiter is also reset on success.

Flow:        Change Password
Docs:        docs/flows.md#change-password, docs/password.md
Performance: Argon2 verify + hash (~200 ms) + O(n) session DELs.
Security:    rejects same-password reuse; audit-logged.

func (*Engine) Close

func (e *Engine) Close()

Close shuts down the Engine by flushing and closing the audit dispatcher. It is safe to call on a nil receiver. After Close returns, no further audit events will be buffered.

Docs: docs/engine.md, docs/audit.md

func (*Engine) ConfirmEmailVerification

func (e *Engine) ConfirmEmailVerification(ctx context.Context, challenge string) error

ConfirmEmailVerification completes email verification using the full challenge string. On success, the account status transitions from AccountPendingVerification to AccountActive.

Flow:        Confirm Email Verification
Docs:        docs/flows.md#email-verification, docs/email_verification.md
Security:    constant-time comparison; attempts tracked.

func (*Engine) ConfirmEmailVerificationCode

func (e *Engine) ConfirmEmailVerificationCode(ctx context.Context, verificationID, code string) error

ConfirmEmailVerificationCode is the preferred method for completing email verification. It accepts the verificationID (safe to log) and the secret code separately. The tenant is determined from the context. For cross-tenant scenarios, use ConfirmEmailVerification with the full challenge string instead.

ConfirmEmailVerificationCode may return an error when input validation, dependency calls, or security checks fail.

func (*Engine) ConfirmLoginMFA

func (e *Engine) ConfirmLoginMFA(ctx context.Context, challengeID, code string) (*LoginResult, error)

ConfirmLoginMFA completes a two-step MFA login by verifying a TOTP code against the challenge ID returned by Engine.LoginWithResult. This is equivalent to ConfirmLoginMFAWithType(ctx, challengeID, code, "totp").

Flow:        Confirm MFA (step 2 of two-step)
Docs:        docs/flows.md#confirm-mfa, docs/mfa.md

func (*Engine) ConfirmLoginMFAWithType

func (e *Engine) ConfirmLoginMFAWithType(ctx context.Context, challengeID, code, mfaType string) (*LoginResult, error)

ConfirmLoginMFAWithType completes a two-step MFA login. mfaType must be "totp" or "backup". On success it returns a LoginResult with tokens.

Flow:        Confirm MFA (step 2 of two-step)
Docs:        docs/flows.md#confirm-mfa, docs/mfa.md
Performance: 2–4 Redis commands (challenge lookup + session creation).
Security:    challenge expires after MFA.LoginChallengeTTL; attempt-limited.

func (*Engine) ConfirmPasswordReset

func (e *Engine) ConfirmPasswordReset(ctx context.Context, challenge, newPassword string) error

ConfirmPasswordReset completes a password reset without MFA verification. Equivalent to ConfirmPasswordResetWithMFA(ctx, challenge, newPassword, "totp", "").

Flow:        Confirm Password Reset
Docs:        docs/flows.md#password-reset, docs/password_reset.md

func (*Engine) ConfirmPasswordResetWithBackupCode

func (e *Engine) ConfirmPasswordResetWithBackupCode(ctx context.Context, challenge, newPassword, backupCode string) error

ConfirmPasswordResetWithBackupCode completes a password reset using a backup code instead of TOTP.

Flow:        Confirm Password Reset (MFA)
Docs:        docs/flows.md#password-reset, docs/password_reset.md, docs/mfa.md

func (*Engine) ConfirmPasswordResetWithMFA

func (e *Engine) ConfirmPasswordResetWithMFA(ctx context.Context, challenge, newPassword, mfaType, mfaCode string) error

ConfirmPasswordResetWithMFA completes a password reset with an optional MFA code. When RequireMFA is enabled in config, mfaCode must be valid. On success the password hash is updated and all user sessions are invalidated.

Flow:        Confirm Password Reset (MFA)
Docs:        docs/flows.md#password-reset, docs/password_reset.md
Performance: Argon2 hash + 2–4 Redis commands + session invalidation.
Security:    challenge consumed atomically; attempts tracked.

func (*Engine) ConfirmPasswordResetWithTOTP

func (e *Engine) ConfirmPasswordResetWithTOTP(ctx context.Context, challenge, newPassword, totpCode string) error

ConfirmPasswordResetWithTOTP completes a password reset with TOTP verification.

Flow:        Confirm Password Reset (MFA)
Docs:        docs/flows.md#password-reset, docs/password_reset.md, docs/mfa.md

func (*Engine) ConfirmTOTPSetup

func (e *Engine) ConfirmTOTPSetup(ctx context.Context, userID, code string) error

ConfirmTOTPSetup verifies a TOTP code against the provisioned secret and, on success, persists the secret and marks TOTP as enabled for the user.

Flow:        TOTP Confirm
Docs:        docs/flows.md#totp-confirm, docs/mfa.md
Security:    rate-limited; replay-protected if configured.

func (*Engine) CreateAccount

func (e *Engine) CreateAccount(ctx context.Context, req CreateAccountRequest) (*CreateAccountResult, error)

CreateAccount creates a new user account. The password is hashed with Argon2, a role mask is assigned, and sessions are optionally issued when Account.AutoLogin is enabled. Returns a CreateAccountResult containing the new userID and (when auto-login is on) access+refresh tokens.

Flow:        Create Account
Docs:        docs/flows.md#create-account, docs/engine.md
Performance: Argon2 hash + 3–5 Redis commands.
Security:    rate-limited per identifier+IP; duplicate detection.

func (*Engine) DeleteAccount

func (e *Engine) DeleteAccount(ctx context.Context, userID string) error

DeleteAccount sets the account status to AccountDeleted and invalidates all of the user’s sessions. Actual data deletion is the caller’s responsibility via the UserProvider.

Flow:        Account Status Transition (delete)
Docs:        docs/flows.md#account-status-transitions, docs/functionality-account-status.md
Security:    audit-logged; emits MetricAccountDeleted.

func (*Engine) DisableAccount

func (e *Engine) DisableAccount(ctx context.Context, userID string) error

DisableAccount sets the account status to AccountDisabled and invalidates all of the user’s sessions, forcing re-authentication.

Flow:        Account Status Transition (disable)
Docs:        docs/flows.md#account-status-transitions, docs/functionality-account-status.md
Performance: 1 provider call + O(n) session DELs.
Security:    audit-logged; emits MetricAccountDisabled.

func (*Engine) DisableTOTP

func (e *Engine) DisableTOTP(ctx context.Context, userID string) error

DisableTOTP removes the TOTP secret for the user, disabling two-factor authentication. Existing sessions are not affected.

Flow:        TOTP Disable
Docs:        docs/flows.md#totp-disable, docs/mfa.md

func (*Engine) EnableAccount

func (e *Engine) EnableAccount(ctx context.Context, userID string) error

EnableAccount sets the account status back to AccountActive and resets the lockout failure counter (if auto-lockout is enabled).

Flow:        Account Status Transition (enable)
Docs:        docs/flows.md#account-status-transitions, docs/functionality-account-status.md
Security:    audit-logged.

func (*Engine) GenerateBackupCodes

func (e *Engine) GenerateBackupCodes(ctx context.Context, userID string) ([]string, error)

GenerateBackupCodes generates a fresh set of one-time backup codes for the user. Existing codes are replaced. The plaintext codes are returned once and must be displayed to the user immediately.

Flow:        Generate Backup Codes
Docs:        docs/flows.md#backup-codes, docs/mfa.md
Security:    codes stored as SHA-256 hashes; originals never persisted.

func (*Engine) GenerateTOTPSetup

func (e *Engine) GenerateTOTPSetup(ctx context.Context, userID string) (*TOTPSetup, error)

GenerateTOTPSetup generates a new TOTP secret for the user and returns a TOTPSetup containing the base32-encoded secret and a QR code URL. The secret is not persisted until Engine.ConfirmTOTPSetup succeeds.

Flow:        TOTP Setup
Docs:        docs/flows.md#totp-setup, docs/mfa.md
Security:    requires active account status.

func (*Engine) GetActiveSessionCount

func (e *Engine) GetActiveSessionCount(ctx context.Context, userID string) (int, error)

GetActiveSessionCount returns the number of active sessions for a user in the tenant derived from context.

Flow:        Introspection
Docs:        docs/flows.md#introspection, docs/introspection.md
Performance: 1 Redis GET (counter).

func (*Engine) GetLoginAttempts

func (e *Engine) GetLoginAttempts(ctx context.Context, identifier string) (int, error)

GetLoginAttempts returns the current failed-login attempt count for the given identifier. Useful for admin dashboards and lockout monitoring.

Docs:        docs/rate_limiting.md, docs/introspection.md
Performance: 1 Redis GET.

func (*Engine) GetSessionInfo

func (e *Engine) GetSessionInfo(ctx context.Context, tenantID, sessionID string) (*SessionInfo, error)

GetSessionInfo returns metadata for a single session by tenant and session ID.

Flow:        Introspection
Docs:        docs/flows.md#introspection, docs/introspection.md
Performance: 1 Redis GET.

func (*Engine) HasPermission

func (e *Engine) HasPermission(mask interface{}, perm string) bool

HasPermission checks whether the given permission bitmask grants the named permission. mask must be one of permission.Mask64, permission.Mask128, permission.Mask256, or permission.Mask512. If RootBitReserved is enabled, root-bit holders implicitly pass.

Docs:        docs/permission.md
Performance: O(1) bitmask check, no Redis, no allocations.

func (*Engine) Health

func (e *Engine) Health(ctx context.Context) HealthStatus

Health performs a lightweight Redis PING and returns availability and round-trip latency. Suitable for readiness probes.

Docs:        docs/ops.md
Performance: 1 Redis PING.

func (*Engine) InvalidateUserSessions

func (e *Engine) InvalidateUserSessions(ctx context.Context, userID string) error

InvalidateUserSessions is an alias for Engine.LogoutAll. It destroys every session for the user in the current tenant.

Flow:        Logout All
Docs:        docs/flows.md#logout

func (*Engine) ListActiveSessions

func (e *Engine) ListActiveSessions(ctx context.Context, userID string) ([]SessionInfo, error)

ListActiveSessions returns metadata for every active session belonging to the user (session ID, created/expires timestamps, role, status).

Flow:        Introspection
Docs:        docs/flows.md#introspection, docs/introspection.md
Performance: 1 SCAN + N GETs.

func (*Engine) LockAccount

func (e *Engine) LockAccount(ctx context.Context, userID string) error

LockAccount sets the account status to AccountLocked and invalidates all of the user’s sessions. This is the manual counterpart to the automatic lockout triggered by too many failed login attempts.

Flow:        Account Status Transition (lock)
Docs:        docs/flows.md#account-status-transitions, docs/functionality-account-status.md
Security:    audit-logged; emits MetricAccountLocked.

func (*Engine) Login

func (e *Engine) Login(ctx context.Context, username, password string) (string, string, error)

Login authenticates a user by identifier and password, returning an access token and a refresh token. If the user has TOTP enabled and RequireForLogin is true, Login returns ErrTOTPRequired; use Engine.LoginWithTOTP or the two-step MFA flow instead.

Flow:        Login (without MFA)
Docs:        docs/flows.md#login-without-mfa, docs/engine.md
Performance: 5–7 Redis commands; dominated by Argon2 hash (~100 ms).
Security:    rate-limited per identifier+IP; timing-equalized on unknown users.

func (*Engine) LoginWithBackupCode

func (e *Engine) LoginWithBackupCode(ctx context.Context, username, password, backupCode string) (string, string, error)

LoginWithBackupCode authenticates a user with identifier, password, and a one-time backup code in a single call. Internally it delegates to Engine.LoginWithResult followed by Engine.ConfirmLoginMFAWithType with type "backup".

Flow:        Login → Confirm MFA (backup code)
Docs:        docs/flows.md#login-with-mfa, docs/mfa.md
Performance: 7–9 Redis commands.
Security:    backup code is consumed on success; rate-limited per user.

func (*Engine) LoginWithResult

func (e *Engine) LoginWithResult(ctx context.Context, username, password string) (*LoginResult, error)

LoginWithResult authenticates a user and returns a LoginResult that includes MFA metadata (MFARequired, MFASession). Use this for the two-step MFA login flow: first call LoginWithResult, then if MFARequired is true, call Engine.ConfirmLoginMFA.

Flow:        Login (step 1 of two-step MFA)
Docs:        docs/flows.md#login-with-mfa, docs/mfa.md
Performance: 5–7 Redis commands; Argon2 dominated.
Security:    rate-limited; timing-equalized.

func (*Engine) LoginWithTOTP

func (e *Engine) LoginWithTOTP(ctx context.Context, username, password, totpCode string) (string, string, error)

LoginWithTOTP authenticates a user with identifier, password, and a TOTP code in a single call. Internally it delegates to Engine.LoginWithResult followed by Engine.ConfirmLoginMFAWithType when MFA is required.

Flow:        Login → Confirm MFA (TOTP)
Docs:        docs/flows.md#login-with-mfa, docs/mfa.md
Performance: 7–9 Redis commands (login + MFA challenge store).
Security:    TOTP rate-limited; replay protection if EnforceReplayProtection is set.

func (*Engine) Logout

func (e *Engine) Logout(ctx context.Context, sessionID string) error

Logout destroys a single session by session ID, using the tenant from context. Equivalent to LogoutInTenant(ctx, tenantFromCtx, sessionID).

Flow:        Logout (single session)
Docs:        docs/flows.md#logout, docs/session.md
Performance: 1–2 Redis commands (DEL + counter decrement).
Security:    audit-logged; session immediately unreachable after return.

func (*Engine) LogoutAll

func (e *Engine) LogoutAll(ctx context.Context, userID string) error

LogoutAll destroys every session for the given userID in the tenant derived from context. Equivalent to LogoutAllInTenant(ctx, ctxTenant, userID).

Flow:        Logout All
Docs:        docs/flows.md#logout, docs/session.md
Performance: O(n) Redis DELs where n = active sessions for the user.

func (*Engine) LogoutAllInTenant

func (e *Engine) LogoutAllInTenant(ctx context.Context, tenantID, userID string) error

LogoutAllInTenant destroys every session for userID within the specified tenant. Called internally after password changes and account status transitions to force re-authentication.

Flow:        Logout All
Docs:        docs/flows.md#logout, docs/session.md
Performance: O(n) Redis DELs.
Security:    audit-logged; emits MetricLogoutAll + MetricSessionInvalidated.

func (*Engine) LogoutByAccessToken

func (e *Engine) LogoutByAccessToken(ctx context.Context, tokenStr string) error

LogoutByAccessToken parses the given access token to extract the session ID and tenant, then destroys that session. Returns ErrTokenInvalid when the token cannot be parsed.

Flow:        Logout (by access token)
Docs:        docs/flows.md#logout, docs/session.md
Performance: 1 JWT parse + 1–2 Redis commands.
Security:    audit-logged.

func (*Engine) LogoutInTenant

func (e *Engine) LogoutInTenant(ctx context.Context, tenantID, sessionID string) error

LogoutInTenant destroys a single session by tenant and session ID.

Flow:        Logout (single session)
Docs:        docs/flows.md#logout, docs/session.md
Performance: 1–2 Redis commands.
Security:    audit-logged.

func (*Engine) MetricsSnapshot

func (e *Engine) MetricsSnapshot() MetricsSnapshot

MetricsSnapshot returns a point-in-time copy of all counters and latency histograms. The returned MetricsSnapshot is a deep copy; callers may inspect or export it without holding any lock.

Docs: docs/metrics.md
Performance: O(n) where n = number of metric IDs. No Redis.

func (*Engine) ProvisionTOTP

func (e *Engine) ProvisionTOTP(ctx context.Context, userID string) (*TOTPProvision, error)

ProvisionTOTP provisions a TOTP secret and returns a TOTPProvision with the raw secret and otpauth:// URI. Like GenerateTOTPSetup but returns the secret in raw form rather than base32.

Flow:        TOTP Setup (alternate)
Docs:        docs/flows.md#totp-setup, docs/mfa.md

func (*Engine) Refresh

func (e *Engine) Refresh(ctx context.Context, refreshToken string) (string, string, error)

Refresh exchanges a valid refresh token for a new access+refresh token pair. The old refresh secret is atomically rotated via a Lua CAS script; presenting a previously-used refresh token triggers reuse detection and invalidates the entire session.

Flow:        Refresh / Rotate
Docs:        docs/flows.md#refresh-token-rotation, docs/session.md
Performance: 3–5 Redis commands (GET + Lua CAS + optional rate check).
Security:    rotation enforced; reuse detection invalidates session immediately.

func (*Engine) RegenerateBackupCodes

func (e *Engine) RegenerateBackupCodes(ctx context.Context, userID, totpCode string) ([]string, error)

RegenerateBackupCodes replaces all existing backup codes after verifying the caller’s TOTP code. Previous codes are invalidated.

Flow:        Regenerate Backup Codes
Docs:        docs/flows.md#backup-codes, docs/mfa.md
Security:    requires valid TOTP code; rate-limited.

func (*Engine) RequestEmailVerification

func (e *Engine) RequestEmailVerification(ctx context.Context, identifier string) (string, error)

RequestEmailVerification starts the email verification flow for the given identifier. Returns a challenge string (or OTP, depending on strategy) that should be delivered to the user out-of-band.

Flow:        Request Email Verification
Docs:        docs/flows.md#email-verification, docs/email_verification.md
Performance: 2–3 Redis commands.
Security:    rate-limited per identifier+IP; enumeration-resistant delay.

func (*Engine) RequestPasswordReset

func (e *Engine) RequestPasswordReset(ctx context.Context, identifier string) (string, error)

RequestPasswordReset starts the password reset flow for the given identifier. Returns a challenge string (or OTP) to be delivered out-of-band. If the identifier is unknown, an enumeration-resistant delay is injected and a non-nil challenge is still returned.

Flow:        Request Password Reset
Docs:        docs/flows.md#password-reset, docs/password_reset.md
Performance: 2–3 Redis commands.
Security:    rate-limited per identifier+IP; timing-equalized.

func (*Engine) SecurityReport

func (e *Engine) SecurityReport() SecurityReport

SecurityReport returns a read-only summary of the engine's active security configuration: signing algorithm, validation mode, Argon2 parameters, TOTP/device-binding enablement, session caps, and more. Useful for admin dashboards and config auditing.

Docs: docs/security.md, docs/config.md
Performance: allocation-only, no Redis.

func (*Engine) UnlockAccount

func (e *Engine) UnlockAccount(ctx context.Context, userID string) error

UnlockAccount re-enables a locked account and resets the lockout failure counter. It is the counterpart to LockAccount (both manual and automatic lockout).

UnlockAccount may return an error when input validation, dependency calls, or security checks fail.

func (*Engine) Validate

func (e *Engine) Validate(ctx context.Context, tokenStr string, routeMode RouteMode) (*AuthResult, error)

Validate parses and validates an access token, optionally performing a Redis session lookup depending on the requested ValidationMode:

  • ModeJWTOnly – signature + claims only, zero Redis.
  • ModeHybrid – JWT validation; Redis lookup used when available.
  • ModeStrict – JWT validation + mandatory session GET.
  • ModeInherit – use the engine’s configured default mode.

Returns an AuthResult containing userID, tenantID, role, and decoded permission mask.

Flow:        Validate
Docs:        docs/flows.md#validate, docs/jwt.md, docs/engine.md
Performance: 0–1 Redis commands depending on mode.
Security:    clock-skew guard, version checks, device binding, account status.

func (*Engine) ValidateAccess

func (e *Engine) ValidateAccess(ctx context.Context, tokenStr string) (*AuthResult, error)

ValidateAccess validates an access token using the engine's configured default ValidationMode. It is equivalent to calling Validate(ctx, tokenStr, ModeInherit).

Flow:        Validate (inherited mode)
Docs:        docs/flows.md#validate, docs/jwt.md
Performance: 0 Redis in JWTOnly, 1 GET in Strict.
Security:    clock-skew guard, permission/role/account version checks.

func (*Engine) VerifyBackupCode

func (e *Engine) VerifyBackupCode(ctx context.Context, userID, code string) error

VerifyBackupCode validates and consumes a one-time backup code for the user. The tenant is derived from context.

Flow:        Consume Backup Code
Docs:        docs/flows.md#backup-codes, docs/mfa.md
Security:    constant-time comparison; code consumed on success.

func (*Engine) VerifyBackupCodeInTenant

func (e *Engine) VerifyBackupCodeInTenant(ctx context.Context, tenantID, userID, code string) error

VerifyBackupCodeInTenant validates and consumes a backup code within a specific tenant.

Flow:        Consume Backup Code
Docs:        docs/flows.md#backup-codes, docs/mfa.md

func (*Engine) VerifyTOTP

func (e *Engine) VerifyTOTP(ctx context.Context, userID, code string) error

VerifyTOTP validates a TOTP code for the user without any login context. Useful for step-up verification in sensitive operations.

Flow:        TOTP Verify
Docs:        docs/flows.md#totp-verify, docs/mfa.md
Security:    rate-limited; replay-protected if configured.

type HealthStatus

type HealthStatus struct {
	RedisAvailable bool
	RedisLatency   time.Duration
}

HealthStatus is an on-demand backend health result.

type JSONWriterSink

type JSONWriterSink = internalaudit.JSONWriterSink

JSONWriterSink is an AuditSink that writes JSON-encoded events to an io.Writer.

Docs: docs/audit.md

func NewJSONWriterSink

func NewJSONWriterSink(w io.Writer) *JSONWriterSink

NewJSONWriterSink creates a JSONWriterSink that writes to w.

Docs: docs/audit.md

type JWTConfig

type JWTConfig struct {
	AccessTTL     time.Duration
	RefreshTTL    time.Duration
	SigningMethod string // "ed25519" (default), "hs256" optional
	PrivateKey    []byte
	PublicKey     []byte
	Issuer        string
	Audience      string
	Leeway        time.Duration
	RequireIAT    bool
	MaxFutureIAT  time.Duration
	KeyID         string
}

JWTConfig controls JWT access token signing and validation parameters.

Docs: docs/jwt.md, docs/config.md

type KeyBuilder

type KeyBuilder interface {
	SessionKey(tenantID, sessionID string) string
	UserVersionKey(tenantID, userID string) string
	RoleVersionKey(tenantID, role string) string
}

KeyBuilder defines the Redis key layout for sessions and version counters.

type LintResult

type LintResult []LintWarning

LintResult wraps a slice of LintWarning with helper methods for filtering and promotion to errors.

func (LintResult) AsError

func (lr LintResult) AsError(minSeverity LintSeverity) error

AsError returns an error if any warning meets or exceeds minSeverity. Returns nil if no warnings meet the threshold. Useful for teams that want to fail startup on high-severity configuration issues:

if err := cfg.Lint().AsError(goAuth.LintHigh); err != nil {
    log.Fatalf("config lint: %v", err)
}

func (LintResult) BySeverity

func (lr LintResult) BySeverity(minSeverity LintSeverity) LintResult

BySeverity returns only warnings at or above the given severity.

func (LintResult) Codes

func (lr LintResult) Codes() []string

Codes returns the warning codes as a string slice (for test assertions).

type LintSeverity

type LintSeverity int

LintSeverity classifies the importance of a lint warning.

const (
	// LintInfo is advisory only — no action required.
	LintInfo LintSeverity = iota
	// LintWarn indicates a configuration that may be sub-optimal in production.
	LintWarn
	// LintHigh indicates a configuration that is dangerous or contradictory.
	LintHigh
)

func (LintSeverity) String

func (s LintSeverity) String() string

String returns a human-readable severity tag.

type LintWarning

type LintWarning struct {
	Code     string       // e.g., "leeway_large", "access_ttl_long"
	Severity LintSeverity // INFO, WARN, or HIGH
	Message  string
}

LintWarning represents a single advisory warning from Config.Lint(). It contains a short code for programmatic matching, a severity level, and a human-readable message.

type LoginResult

type LoginResult struct {
	AccessToken  string
	RefreshToken string

	MFARequired bool
	MFAType     string
	MFASession  string
}

LoginResult is returned by Engine.LoginWithResult and Engine.ConfirmLoginMFA. It includes tokens when authentication succeeds, or MFA metadata when a second factor is required.

type MetricID

type MetricID = internalmetrics.MetricID

MetricID identifies a specific counter or histogram bucket in the in-process metrics system.

Docs: docs/metrics.md

type Metrics

type Metrics = internalmetrics.Metrics

Metrics holds atomic counters and optional latency histograms.

Docs: docs/metrics.md

func NewMetrics

func NewMetrics(cfg MetricsConfig) *Metrics

NewMetrics creates a new Metrics instance configured by the given MetricsConfig. When Enabled is false, all operations are no-ops.

Docs: docs/metrics.md

type MetricsConfig

type MetricsConfig struct {
	Enabled                 bool
	EnableLatencyHistograms bool
}

MetricsConfig controls in-process metrics: counters and optional latency histograms.

Docs: docs/metrics.md, docs/config.md

type MetricsSnapshot

type MetricsSnapshot = internalmetrics.Snapshot

MetricsSnapshot is a point-in-time deep copy of all metrics.

Docs: docs/metrics.md

type MultiTenantConfig

type MultiTenantConfig struct {
	Enabled          bool
	TenantHeader     string
	EnforceIsolation bool
}

MultiTenantConfig enables tenant-scoped session isolation.

Docs: docs/config.md

type NoOpSink

type NoOpSink = internalaudit.NoOpSink

NoOpSink is an AuditSink that silently discards all events.

type PasswordConfig

type PasswordConfig struct {
	Memory         uint32 // in KB
	Time           uint32
	Parallelism    uint8
	SaltLength     uint32
	KeyLength      uint32
	UpgradeOnLogin bool
}

PasswordConfig holds Argon2id hashing parameters.

Docs: docs/password.md, docs/config.md

type PasswordConfigReport

type PasswordConfigReport struct {
	Memory      uint32
	Time        uint32
	Parallelism uint8
	SaltLength  uint32
	KeyLength   uint32
}

PasswordConfigReport contains the Argon2 parameters active in the engine.

type PasswordResetConfig

type PasswordResetConfig struct {
	Enabled                  bool
	Strategy                 ResetStrategyType
	ResetTTL                 time.Duration
	MaxAttempts              int
	EnableIPThrottle         bool
	EnableIdentifierThrottle bool
	OTPDigits                int
}

PasswordResetConfig controls the password-reset flow: strategy, TTLs, rate limits, and attempt caps.

Docs: docs/password_reset.md, docs/config.md

type PermissionConfig

type PermissionConfig struct {
	MaxBits         int  // 64, 128, 256, 512 (hard cap)
	RootBitReserved bool // if true, highest bit is root/super admin
}

PermissionConfig controls the bitmask RBAC system: max bits, root-bit reservation, and versioning.

Docs: docs/permission.md, docs/config.md

type PermissionMask

type PermissionMask interface {
	Has(bit int) bool
	Set(bit int)
	Raw() any
}

PermissionMask is the interface satisfied by all bitmask widths (permission.Mask64, permission.Mask128, permission.Mask256, permission.Mask512).

Docs: docs/permission.md

type ResetStrategyType

type ResetStrategyType int

ResetStrategyType selects the password-reset challenge delivery strategy (link-based or OTP-based).

Docs: docs/password_reset.md
const (
	// ResetToken is an exported constant or variable used by the authentication engine.
	ResetToken ResetStrategyType = iota
	// ResetOTP is an exported constant or variable used by the authentication engine.
	ResetOTP
	// ResetUUID is an exported constant or variable used by the authentication engine.
	ResetUUID
)

type ResultConfig

type ResultConfig struct {
	IncludeRole        bool
	IncludePermissions bool
}

ResultConfig controls what data is included in AuthResult returned by Engine.Validate.

type RoleStore

type RoleStore interface {
	GetRoleMask(ctx context.Context, tenantID, role string) (PermissionMask, uint32, error)
}

RoleStore is a legacy role-lookup interface.

type RouteMode

type RouteMode = ValidationMode

RouteMode is the per-route override mode for Engine.Validate. It intentionally reuses the same constants (ModeInherit/ModeStrict/ModeJWTOnly).

type SecurityConfig

type SecurityConfig struct {
	ProductionMode               bool
	EnableIPBinding              bool
	EnableUserAgentBinding       bool
	EnableIPThrottle             bool
	EnableRefreshThrottle        bool
	EnforceRefreshRotation       bool
	EnforceRefreshReuseDetection bool
	MaxLoginAttempts             int
	LoginCooldownDuration        time.Duration
	MaxRefreshAttempts           int
	RefreshCooldownDuration      time.Duration
	StrictMode                   bool
	RequireSecureCookies         bool
	SameSitePolicy               http.SameSite
	CSRFProtection               bool
	EnablePermissionVersionCheck bool
	EnableRoleVersionCheck       bool
	EnableAccountVersionCheck    bool
	AutoLockoutEnabled           bool
	AutoLockoutThreshold         int
	AutoLockoutDuration          time.Duration // 0 = manual unlock only
}

SecurityConfig holds security-related settings: rate limits, lockout, refresh rotation, version checking, and production mode flags.

Docs: docs/security.md, docs/config.md

type SecurityReport

type SecurityReport struct {
	ProductionMode               bool
	SigningAlgorithm             string
	ValidationMode               ValidationMode
	StrictMode                   bool
	AccessTTL                    time.Duration
	RefreshTTL                   time.Duration
	Argon2                       PasswordConfigReport
	TOTPEnabled                  bool
	BackupEnabled                bool
	DeviceBindingEnabled         bool
	RefreshRotationEnabled       bool
	RefreshReuseDetectionEnabled bool
	SessionCapsActive            bool
	RateLimitingActive           bool
	EmailVerificationActive      bool
	PasswordResetActive          bool
}

SecurityReport is a read-only snapshot of the engine’s security posture, returned by Engine.SecurityReport.

Docs: docs/security.md

type SessionConfig

type SessionConfig struct {
	RedisPrefix             string
	SlidingExpiration       bool
	AbsoluteSessionLifetime time.Duration
	JitterEnabled           bool
	JitterRange             time.Duration
	MaxSessionSize          int
	SessionEncoding         string // "binary" (default) or "msgpack"
}

SessionConfig controls Redis session storage, sliding expiration, and jitter.

Docs: docs/session.md, docs/config.md

type SessionHardeningConfig

type SessionHardeningConfig struct {
	MaxSessionsPerUser   int
	MaxSessionsPerTenant int
	EnforceSingleSession bool
	ConcurrentLoginLimit int
	EnableReplayTracking bool
	MaxClockSkew         time.Duration
}

SessionHardeningConfig controls session limits: max per user/tenant, single-session enforcement, concurrent login caps, replay tracking, and clock-skew tolerance.

Docs: docs/session.md, docs/config.md

type SessionInfo

type SessionInfo struct {
	SessionID         string
	CreatedAt         int64
	ExpiresAt         int64
	Role              string
	Status            AccountStatus
	AccountVersion    uint32
	PermissionVersion uint32
}

SessionInfo is the safe introspection view for a session. It intentionally excludes refresh hashes, token material, and raw mask bits.

type TOTPConfig

type TOTPConfig struct {
	Enabled                     bool
	Issuer                      string
	Digits                      int
	Period                      int
	Algorithm                   string
	Skew                        int
	EnforceReplayProtection     bool
	MFALoginChallengeTTL        time.Duration
	MFALoginMaxAttempts         int
	BackupCodeCount             int
	BackupCodeLength            int
	BackupCodeMaxAttempts       int
	BackupCodeCooldown          time.Duration
	RequireForLogin             bool
	RequireBackupForLogin       bool
	RequireForSensitive         bool
	RequireForPasswordReset     bool
	RequireTOTPForPasswordReset bool

	// MaxVerifyAttempts is the maximum number of TOTP verification
	// attempts before rate limiting kicks in. Default: 5.
	MaxVerifyAttempts int

	// VerifyAttemptCooldown is the window after the first failed attempt
	// in which MaxVerifyAttempts are counted. Default: 1m.
	VerifyAttemptCooldown time.Duration
}

TOTPConfig controls TOTP-based two-factor authentication: issuer, period, digits, algorithm, skew, backup codes, and enforcement flags.

Docs: docs/mfa.md, docs/config.md

type TOTPProvision

type TOTPProvision struct {
	Secret string
	URI    string
}

TOTPProvision holds the raw TOTP secret and otpauth:// URI returned by Engine.ProvisionTOTP.

type TOTPRecord

type TOTPRecord struct {
	Secret          []byte
	Enabled         bool
	Verified        bool
	LastUsedCounter int64
}

TOTPRecord is retrieved from [UserProvider.GetTOTPSecret]. It carries the encrypted secret, enabled/verified flags, and the last-used HOTP counter for replay protection.

type TOTPSetup

type TOTPSetup struct {
	SecretBase32 string
	QRCodeURL    string
}

TOTPSetup holds the base32-encoded TOTP secret and QR code URL returned by Engine.GenerateTOTPSetup.

type User

type User struct {
	ID             string
	TenantID       string
	PasswordHash   string
	PermissionMask PermissionMask
	Role           string
	PermVersion    uint32
	RoleVersion    uint32
}

User is a minimal user representation used by the legacy UserStore interface. Prefer UserRecord for new integrations.

type UserProvider

type UserProvider interface {
	GetUserByIdentifier(identifier string) (UserRecord, error)
	GetUserByID(userID string) (UserRecord, error)
	UpdatePasswordHash(userID string, newHash string) error
	CreateUser(ctx context.Context, input CreateUserInput) (UserRecord, error)
	UpdateAccountStatus(ctx context.Context, userID string, status AccountStatus) (UserRecord, error)
	GetTOTPSecret(ctx context.Context, userID string) (*TOTPRecord, error)
	EnableTOTP(ctx context.Context, userID string, secret []byte) error
	DisableTOTP(ctx context.Context, userID string) error
	MarkTOTPVerified(ctx context.Context, userID string) error
	UpdateTOTPLastUsedCounter(ctx context.Context, userID string, counter int64) error
	GetBackupCodes(ctx context.Context, userID string) ([]BackupCodeRecord, error)
	ReplaceBackupCodes(ctx context.Context, userID string, codes []BackupCodeRecord) error
	ConsumeBackupCode(ctx context.Context, userID string, codeHash [32]byte) (bool, error)
}

UserProvider is the primary interface that callers must implement to integrate goAuth with their user database. It covers credential lookup, account creation, password updates, TOTP secret management, and backup code storage.

Docs: docs/engine.md, docs/usage.md

type UserRecord

type UserRecord struct {
	UserID            string
	Identifier        string
	TenantID          string
	PasswordHash      string
	TOTPEnabled       bool
	Status            AccountStatus
	Role              string
	PermissionVersion uint32
	RoleVersion       uint32
	AccountVersion    uint32
}

UserRecord is the full account record returned by UserProvider. It carries credential hashes, status, role, and versioning counters.

type UserStore

type UserStore interface {
	GetByIdentifier(ctx context.Context, identifier string) (*User, error)
	UpdatePermissionMask(ctx context.Context, userID string, mask PermissionMask) error
}

UserStore is a legacy credential-lookup interface. Prefer UserProvider for full account lifecycle support.

type ValidationMode

type ValidationMode int

ValidationMode determines how access tokens are validated: JWTOnly (0 Redis), Hybrid, or Strict (1 Redis GET).

Docs: docs/jwt.md, docs/engine.md
const (
	// ModeInherit is an exported constant or variable used by the authentication engine.
	ModeInherit ValidationMode = -1

	// ModeJWTOnly validates access tokens using JWT claims only (no Redis access in validation path).
	ModeJWTOnly ValidationMode = iota
	// ModeHybrid validates by JWT by default; strict routes can still force Redis-backed checks.
	ModeHybrid
	// ModeStrict validates every request against Redis and fails closed on Redis/session errors.
	ModeStrict
)

type VerificationStrategyType

type VerificationStrategyType int

VerificationStrategyType selects the email verification challenge strategy (link-based or OTP-based).

Docs: docs/email_verification.md
const (
	// VerificationToken is an exported constant or variable used by the authentication engine.
	VerificationToken VerificationStrategyType = iota
	// VerificationOTP is an exported constant or variable used by the authentication engine.
	VerificationOTP
	// VerificationUUID is an exported constant or variable used by the authentication engine.
	VerificationUUID
)

Directories

Path Synopsis
cmd
goauth-loadtest command
examples
http-minimal command
Package main demonstrates a minimal HTTP integration with goAuth.
Package main demonstrates a minimal HTTP integration with goAuth.
Package internal contains helper utilities that are intentionally private to goAuth, including secure random generation and device fingerprint helpers.
Package internal contains helper utilities that are intentionally private to goAuth, including secure random generation and device fingerprint helpers.
audit
Package audit implements async event dispatching for security-relevant operations.
Package audit implements async event dispatching for security-relevant operations.
flows
Package flows contains pure-function orchestrators for every Engine operation.
Package flows contains pure-function orchestrators for every Engine operation.
limiters
Package limiters provides domain-specific rate limiters built on top of the internal/rate primitives.
Package limiters provides domain-specific rate limiters built on top of the internal/rate primitives.
metrics
Package metrics provides lock-free counters and latency histograms for goAuth observability.
Package metrics provides lock-free counters and latency histograms for goAuth observability.
rate
Package rate provides internal primitives used to build Redis-backed rate limit keys, errors, and limiter behavior for security-sensitive authentication workflows.
Package rate provides internal primitives used to build Redis-backed rate limit keys, errors, and limiter behavior for security-sensitive authentication workflows.
security
Package security contains CLI tooling for automated security analysis: performance regression gates, static-analysis scanner baselines, and related helper scripts.
Package security contains CLI tooling for automated security analysis: performance regression gates, static-analysis scanner baselines, and related helper scripts.
stores
Package stores provides Redis-backed, short-lived record stores for security-sensitive authentication flows: password reset, email verification, and MFA login challenges.
Package stores provides Redis-backed, short-lived record stores for security-sensitive authentication flows: password reset, email verification, and MFA login challenges.
Package jwt manages access-token issuance and verification using configured signing keys and strict validation semantics suitable for low-latency authentication paths.
Package jwt manages access-token issuance and verification using configured signing keys and strict validation semantics suitable for low-latency authentication paths.
metrics
export/internaldefs
Package internaldefs exposes stable metric name and label definitions shared by exporter implementations.
Package internaldefs exposes stable metric name and label definitions shared by exporter implementations.
export/otel
Package otel provides OpenTelemetry metric exporter bindings for goAuth counters and histograms.
Package otel provides OpenTelemetry metric exporter bindings for goAuth counters and histograms.
export/prometheus
Package prometheus provides Prometheus collectors for goAuth metrics.
Package prometheus provides Prometheus collectors for goAuth metrics.
Package middleware exposes HTTP middleware adapters for JWT-only, hybrid, and strict authorization enforcement modes built on top of goAuth.Engine validation.
Package middleware exposes HTTP middleware adapters for JWT-only, hybrid, and strict authorization enforcement modes built on top of goAuth.Engine validation.
Package password implements password hashing and verification with Argon2id defaults.
Package password implements password hashing and verification with Argon2id defaults.
Package permission provides fixed-size bitmask types, a permission registry, and role composition helpers used by goAuth authorization checks.
Package permission provides fixed-size bitmask types, a permission registry, and role composition helpers used by goAuth authorization checks.
Package refresh implements parsing and validation utilities for opaque rotating refresh tokens.
Package refresh implements parsing and validation utilities for opaque rotating refresh tokens.
security
Package session provides Redis-backed session persistence and compact binary session encoding for authentication hot paths.
Package session provides Redis-backed session persistence and compact binary session encoding for authentication hot paths.

Jump to

Keyboard shortcuts

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