goauth

package module
v2.0.0 Latest Latest
Warning

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

Go to latest
Published: Nov 22, 2025 License: MIT Imports: 11 Imported by: 0

README

goauth

Go Reference

Pluggable authentication for Go. Build username/password or JWT-based auth with a simple strategy interface, configurable JWT access/refresh token issuers with multi-session support, and typed errors for clean, predictable error handling.

Works as an auth core you can drop into HTTP APIs, gRPC, or CLIs.

Version

Current: v2.0.0

This is a major version with breaking changes from v1. See Migration from v1 for upgrade guide.

Installation

go get github.com/openframebox/goauth/v2

For v1 (legacy):

go get github.com/openframebox/goauth

Features

  • Multi-session support - Users can have multiple active sessions (e.g., phone + laptop)
  • Token rotation - Proper refresh token rotation with old token invalidation
  • Multiple signing algorithms - HS256/384/512, RS256/384/512, ES256/384/512
  • Event hooks - OnBeforeAuthenticate, OnAfterAuthenticate, OnTokenIssued, OnTokenRevoked
  • Rate limiting - Built-in interfaces for rate limiting strategies
  • Password validation - Optional bcrypt/argon2 integration
  • Thread-safe - Safe for concurrent use
  • Typed errors - Categorized errors for consistent HTTP responses

Concepts

  • Strategy: pluggable auth mechanism (Local, JWT, OAuth, SSO). Implement Name() and Authenticate().
  • Authenticatable: minimal user interface (GetID, GetUsername, GetEmail, GetExtra).
  • TokenIssuer: creates/verifies access tokens and manages refresh tokens.
    • DefaultTokenIssuer: basic HS256 JWT issuer
    • SessionTokenIssuer: multi-session aware issuer with configurable signing
  • SessionInfo: session metadata (ID, device, IP, expiry) for multi-session support
  • Typed Errors: CredentialError, TokenError, ConfigError, NotFoundError, InternalError, RateLimitError, ValidationError, SessionError

Quick Start

go run ./example                    # Basic multi-session demo
go run ./example/http_server        # HTTP server example

Basic Setup (DefaultTokenIssuer)

For simple use cases without multi-session support:

package main

import (
    "context"
    goauth "github.com/openframebox/goauth/v2"
)

func setup() *goauth.GoAuth {
    // Configure token issuer
    ti := goauth.NewDefaultTokenIssuer("supersecret")
    ti.SetIssuer("api.example.com")
    ti.SetAudience([]string{"api.example.com"})

    // Required: refresh token storage
    ti.StoreRefreshTokenWith(func(ctx context.Context, a goauth.Authenticatable, tok *goauth.Token, oldToken *string) error {
        // oldToken is nil for initial login, non-nil for refresh (rotation)
        if oldToken != nil {
            // Invalidate the old token
        }
        // Store tok.Value with user a.GetID()
        return nil
    })

    ti.ValidateRefreshTokenWith(func(ctx context.Context, token string) (goauth.Authenticatable, error) {
        // Lookup token -> user; return error if invalid
        return &goauth.User{ID: "user-123"}, nil
    })

    ti.RevokeRefreshTokenWith(func(ctx context.Context, token string) error {
        // Delete the token from storage
        return nil
    })

    // Build orchestrator
    ga := goauth.New()
    ga.SetTokenIssuer(ti)

    // Register strategies using builder pattern
    ga.RegisterStrategy(goauth.NewLocalStrategy(func(ctx context.Context, p goauth.AuthParams) (goauth.Authenticatable, error) {
        // Validate credentials
        return &goauth.User{ID: "user-" + p.UsernameOrEmail, Username: p.UsernameOrEmail}, nil
    }))

    ga.RegisterStrategy(goauth.NewJWTStrategy(ti).WithExpectedType(goauth.AccessToken))

    return ga
}

Multi-Session Setup (SessionTokenIssuer)

For apps that need multi-device login, session management, and advanced signing:

package main

import (
    "context"
    "time"
    goauth "github.com/openframebox/goauth/v2"
)

func setup() *goauth.GoAuth {
    // Create key provider (supports HS256/384/512, RS256/384/512, ES256/384/512)
    keyProvider, _ := goauth.NewHMACKeyProvider([]byte("supersecret"), goauth.HS256)

    // Build session-aware token issuer
    issuer, _ := goauth.NewSessionAwareTokenIssuer().
        WithKeyProvider(keyProvider).
        WithIssuer("api.example.com").
        WithAudience([]string{"api.example.com"}).
        WithAccessTokenTTL(15 * time.Minute).
        WithRefreshTokenTTL(7 * 24 * time.Hour).
        WithSessionStore(
            storeSession,      // Store session + token
            validateSession,   // Validate token -> user + session
            revokeSession,     // Revoke single session
            revokeAllSessions, // Revoke all user sessions
        ).
        WithListSessions(listSessions).
        WithGetSession(getSession).
        WithSessionMetadataExtractor(func(ctx context.Context) map[string]any {
            // Extract device info, IP, user agent from context
            return map[string]any{"device": "browser", "ip": "127.0.0.1"}
        }).
        Build()

    ga := goauth.New()
    ga.SetTokenIssuer(issuer)

    // Register strategies
    ga.RegisterStrategy(goauth.NewLocalStrategy(lookupUser))
    ga.RegisterStrategy(goauth.NewJWTStrategy(issuer).WithExpectedType(goauth.AccessToken))

    return ga
}

// Session store callbacks
func storeSession(ctx context.Context, auth goauth.Authenticatable, session *goauth.SessionInfo, token *goauth.Token, oldToken *string) error {
    // If oldToken != nil, invalidate it (rotation)
    // Store session with token
    return nil
}

func validateSession(ctx context.Context, token string) (goauth.Authenticatable, *goauth.SessionInfo, error) {
    // Lookup token -> user + session
    return user, session, nil
}

func revokeSession(ctx context.Context, auth goauth.Authenticatable, sessionID string) error {
    // Delete session by ID
    return nil
}

func revokeAllSessions(ctx context.Context, auth goauth.Authenticatable) error {
    // Delete all sessions for user
    return nil
}

func listSessions(ctx context.Context, auth goauth.Authenticatable) ([]*goauth.SessionInfo, error) {
    // Return all active sessions for user
    return sessions, nil
}

func getSession(ctx context.Context, token string) (*goauth.SessionInfo, error) {
    // Get session info by token
    return session, nil
}

Choosing a Token Issuer

Feature DefaultTokenIssuer SessionTokenIssuer
Signing algorithms HS256 only HS256/384/512, RS256/384/512, ES256/384/512
Multi-device login No session isolation Each device = unique session
Session management None ListSessions, RevokeSession, RevokeAllSessions
JWT sid claim Not included Session ID embedded in access token
Session metadata None Device, IP, user agent tracking
Configuration style Setter methods Builder pattern
Storage callbacks Token-centric Session-centric

Use DefaultTokenIssuer when:

  • Simple single-session apps
  • You only need basic JWT with HS256
  • You manage token storage yourself without session semantics

Use SessionTokenIssuer when:

  • Users log in from multiple devices (phone + laptop)
  • You need "see all active sessions" or "logout all devices" features
  • You want flexible signing algorithms (RSA, ECDSA)
  • You need session metadata (device info, IP tracking)

Core Flows

1) Login and Issue Tokens
// Returns individual tokens
res, access, refresh, err := ga.AuthenticateAndIssueTokens(ctx, "local", goauth.AuthParams{
    UsernameOrEmail: "alice",
    Password:        "s3cret",
})

// Or returns TokenPair
res, pair, err := ga.AuthenticateAndIssueTokenPair(ctx, "local", params)
// pair.Access, pair.Refresh, pair.Access.SessionID
2) Authenticate Requests with JWT
res, err := ga.Authenticate(ctx, "jwt", goauth.AuthParams{Token: bearer})
// res.Authenticatable is your user
3) Refresh Tokens (with rotation)
// Old refresh token is passed to storage for invalidation
pair, err := ga.RefreshTokenPair(ctx, refreshToken)
// pair.Access (new), pair.Refresh (new, old is invalidated)
4) Revoke Tokens / Sessions
// Revoke single token
err := ga.RevokeToken(ctx, refreshToken)

// Revoke specific session (requires SessionTokenIssuer)
err := ga.RevokeSession(ctx, user, sessionID)

// Revoke all sessions (logout everywhere)
err := ga.RevokeAllTokens(ctx, user)
5) List Active Sessions
sessions, err := ga.ListSessions(ctx, user)
for _, s := range sessions {
    fmt.Printf("Session %s: device=%s, expires=%s\n",
        s.ID, s.Metadata["device"], s.ExpiresAt)
}

Event Hooks

Add logging, audit trails, or custom logic:

type MyHooks struct {
    goauth.NoOpEventHooks // Embed to only override what you need
}

func (h *MyHooks) OnBeforeAuthenticate(ctx context.Context, strategy string, params goauth.AuthParams) error {
    // Rate limiting, logging, etc.
    // Return error to block authentication
    return nil
}

func (h *MyHooks) OnAfterAuthenticate(ctx context.Context, strategy string, result *goauth.AuthResult, err error) {
    if err != nil {
        log.Printf("Auth failed for strategy %s: %v", strategy, err)
    } else {
        log.Printf("User %s authenticated via %s", result.Authenticatable.GetID(), strategy)
    }
}

func (h *MyHooks) OnTokenIssued(ctx context.Context, auth goauth.Authenticatable, tokens *goauth.TokenPair) {
    log.Printf("Tokens issued for user %s, session %s", auth.GetID(), tokens.Access.SessionID)
}

func (h *MyHooks) OnTokenRevoked(ctx context.Context, auth goauth.Authenticatable, token string) {
    log.Printf("Token revoked for user %s", auth.GetID())
}

// Register hooks
ga.SetEventHooks(&MyHooks{})

Strategy Enhancements

LocalStrategy with Password Validation & Rate Limiting
strategy := goauth.NewLocalStrategy(lookupUser).
    WithName("local").
    WithPasswordValidator(
        func(plain, hashed string) bool {
            return bcrypt.CompareHashAndPassword([]byte(hashed), []byte(plain)) == nil
        },
        func(user goauth.Authenticatable) string {
            return user.(*MyUser).HashedPassword
        },
    ).
    WithRateLimiter(
        func(ctx context.Context, identifier string) error {
            // Return goauth.ErrRateLimitExceeded if blocked
            return nil
        },
        func(ctx context.Context, identifier string, success bool) {
            // Record attempt for rate limiting
        },
    ).
    WithUsernameNormalizer(func(username string) string {
        return strings.ToLower(strings.TrimSpace(username))
    })
JWTStrategy with Token Type & Revocation Check
strategy := goauth.NewJWTStrategy(issuer).
    WithName("jwt").
    WithExpectedType(goauth.AccessToken).  // Reject refresh tokens
    WithRevocationCheck(func(ctx context.Context, token string) bool {
        // Return true if token is revoked
        return isRevoked(token)
    })

Signing Algorithms

// HMAC (symmetric)
kp, _ := goauth.NewHMACKeyProvider([]byte("secret"), goauth.HS256)
kp, _ := goauth.NewHMACKeyProvider([]byte("secret"), goauth.HS384)
kp, _ := goauth.NewHMACKeyProvider([]byte("secret"), goauth.HS512)

// RSA (asymmetric)
kp, _ := goauth.NewRSAKeyProvider(privateKey, publicKey, goauth.RS256)

// ECDSA (asymmetric)
kp, _ := goauth.NewECDSAKeyProvider(privateKey, publicKey, goauth.ES256)

HTTP Integration

func loginHandler(w http.ResponseWriter, r *http.Request) {
    var req LoginRequest
    json.NewDecoder(r.Body).Decode(&req)

    _, pair, err := ga.AuthenticateAndIssueTokenPair(r.Context(), "local", goauth.AuthParams{
        UsernameOrEmail: req.Username,
        Password:        req.Password,
    })
    if err != nil {
        resp := goauth.ErrorResponseForError(err)
        w.WriteHeader(resp.Status)
        json.NewEncoder(w).Encode(resp)
        return
    }

    json.NewEncoder(w).Encode(map[string]any{
        "access_token":  pair.Access.Value,
        "refresh_token": pair.Refresh.Value,
        "expires_in":    int(pair.Access.ExpiresIn.Seconds()),
        "session_id":    pair.Access.SessionID,
    })
}

func authMiddleware(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        token := strings.TrimPrefix(r.Header.Get("Authorization"), "Bearer ")
        result, err := ga.Authenticate(r.Context(), "jwt", goauth.AuthParams{Token: token})
        if err != nil {
            resp := goauth.ErrorResponseForError(err)
            w.WriteHeader(resp.Status)
            json.NewEncoder(w).Encode(resp)
            return
        }
        ctx := context.WithValue(r.Context(), "user", result.Authenticatable)
        next.ServeHTTP(w, r.WithContext(ctx))
    })
}

Error Types & HTTP Mapping

Error Type HTTP Status Error Code
CredentialError 401 invalid_credentials
TokenError 401 token_error / token_missing / token_invalid / token_expired / token_revoked
ValidationError 400 validation_error
RateLimitError 429 rate_limit_exceeded
NotFoundError 404 not_found / strategy_not_found / session_not_found
ConfigError 500 config_error
InternalError 500 internal_error
SessionError 401 session_error
// Get structured error response
resp := goauth.ErrorResponseForError(err)
// resp.Status, resp.Code, resp.Message, resp.Fields (for validation), resp.RetryAfter (for rate limit)

// Or individual helpers
status := goauth.HTTPStatusForError(err)
code := goauth.ErrorCodeForError(err)
retryAfter := goauth.RetryAfterForError(err)

Thread Safety

GoAuth is safe for concurrent use:

// Strategy registration is mutex-protected
ga.RegisterStrategy(strategy)
ga.UnregisterStrategy("oauth")
ga.HasStrategy("local")
ga.ListStrategies()

Singleton Access

For convenience when DI isn't practical:

ga.RegisterSingleton()              // Overwrite allowed
_ = ga.RegisterSingletonOnce()      // Set once, error on second

// Later
ga = goauth.GetInstance()

// Testing
restore := goauth.ReplaceSingletonForTest(mockGA)
defer restore()

Examples

# Multi-session demo
go run ./example

# HTTP server with login, refresh, logout, sessions endpoints
go run ./example/http_server

The HTTP server example provides:

  • POST /login - Authenticate and get tokens
  • POST /refresh - Refresh tokens
  • POST /logout - Revoke current session
  • POST /logout-all - Revoke all sessions
  • GET /me - Get current user (protected)
  • GET /sessions - List active sessions (protected)

Migration from v1

Breaking Changes
  1. Module path changed: Import path is now github.com/openframebox/goauth/v2

    // v1
    import goauth "github.com/openframebox/goauth"
    // v2
    import goauth "github.com/openframebox/goauth/v2"
    
  2. TokenIssuer interface: CreateRefreshToken signature changed

    // v1
    CreateRefreshToken(ctx, auth, refreshing bool) (*Token, error)
    // v2
    CreateRefreshToken(ctx, auth, oldToken *string) (*Token, error)
    
  3. StoreRefreshTokenFunc: signature changed

    // v1
    func(ctx, auth, token, refreshing bool) error
    // v2
    func(ctx, auth, token, oldToken *string) error
    
  4. Strategy constructors: use builder pattern

    // v1
    &goauth.LocalStrategy{LookupUserWith: fn}
    // v2
    goauth.NewLocalStrategy(fn)
    
    // v1
    &goauth.JWTStrategy{TokenIssuer: ti}
    // v2
    goauth.NewJWTStrategy(ti)
    
  5. Token struct: new fields added

    • Type (TokenType) - "access" or "refresh"
    • IssuedAt (time.Time)
    • SessionID (string)
  6. New required method on TokenIssuer: RevokeRefreshToken(ctx, token string) error

  7. GoAuth methods: New TokenPair returning methods added

    • IssueTokenPair() alongside IssueTokens()
    • RefreshTokenPair() alongside RefreshToken()
    • AuthenticateAndIssueTokenPair() alongside AuthenticateAndIssueTokens()
New Features in v2
  • Multi-session support with SessionTokenIssuer
  • Multiple signing algorithms (HS256/384/512, RS256/384/512, ES256/384/512)
  • Event hooks (AuthEventHooks interface)
  • Rate limiting support in strategies
  • Password validation in LocalStrategy
  • Token type validation in JWTStrategy
  • Thread-safe strategy registration with sync.RWMutex
  • New error types: RateLimitError, ValidationError, SessionError
  • Session management: ListSessions, RevokeSession, RevokeAllTokens

Security Notes

  • Use strong, rotated secrets. Keep them out of source control.
  • Set correct issuer and audience claims.
  • Keep access tokens short-lived (5-15 min).
  • Implement proper refresh token rotation.
  • Revoke tokens on logout and suspicious activity.
  • Use rate limiting on authentication endpoints.
  • Hash passwords with bcrypt/argon2.

License

MIT

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	// Credential errors
	ErrInvalidCredentials = &CredentialError{Msg: "invalid credentials"}
	ErrUserNotFound       = &CredentialError{Msg: "user not found"}

	// Token errors
	ErrMissingToken      = &TokenError{Msg: "token is required"}
	ErrInvalidToken      = &TokenError{Msg: "invalid token"}
	ErrExpiredToken      = &TokenError{Msg: "expired token"}
	ErrTokenRevoked      = &TokenError{Msg: "token has been revoked"}
	ErrTokenTypeMismatch = &TokenError{Msg: "unexpected token type"}

	// Config errors
	ErrTokenIssuerUnset  = &ConfigError{Msg: "token issuer is not set"}
	ErrKeyProviderUnset  = &ConfigError{Msg: "key provider is not set"}
	ErrSessionStoreUnset = &ConfigError{Msg: "session store is not set"}

	// Not found errors
	ErrStrategyNotFound = &NotFoundError{Msg: "strategy not found"}
	ErrSessionNotFound  = &NotFoundError{Msg: "session not found"}

	// Rate limit errors
	ErrRateLimitExceeded = &RateLimitError{Msg: "rate limit exceeded"}
)

Convenience sentinels for common cases (use errors.As to match by type).

Functions

func ErrorCodeForError

func ErrorCodeForError(err error) string

ErrorCodeForError returns a stable, client-facing error code string. Use alongside HTTPStatusForError to build consistent error responses.

func HTTPStatusForError

func HTTPStatusForError(err error) int

HTTPStatusForError maps typed goauth errors to an HTTP status code. Fallthrough defaults to 500 for unknown error types.

func NewConfigError

func NewConfigError(msg string, err error) error

func NewCredentialError

func NewCredentialError(msg string, err error) error

Helper constructors

func NewInternalError

func NewInternalError(msg string, err error) error

func NewNotFoundError

func NewNotFoundError(msg string, err error) error

func NewRateLimitError

func NewRateLimitError(msg string, retryAfter time.Duration) error

func NewSessionError

func NewSessionError(msg string, sessionID string, err error) error

func NewTokenError

func NewTokenError(msg string, err error) error

func NewValidationError

func NewValidationError(msg string, fields map[string]string) error

func ReplaceSingletonForTest

func ReplaceSingletonForTest(ga *GoAuth) (restore func())

ReplaceSingletonForTest replaces the current singleton and returns a restore function that reverts to the previous instance. Intended for tests.

func RetryAfterForError

func RetryAfterForError(err error) time.Duration

RetryAfterForError returns the Retry-After header value for rate limit errors Returns 0 if the error is not a rate limit error

func WithContext

func WithContext(err error, format string, args ...any) error

WithContext attaches context to an error without losing type info. Exported for use by strategies and other packages.

Types

type AuthEventHooks

type AuthEventHooks interface {
	// OnBeforeAuthenticate is called before authentication
	// Return an error to prevent authentication (e.g., rate limiting)
	OnBeforeAuthenticate(ctx context.Context, strategy string, params AuthParams) error

	// OnAfterAuthenticate is called after authentication (success or failure)
	OnAfterAuthenticate(ctx context.Context, strategy string, result *AuthResult, err error)

	// OnTokenIssued is called when tokens are issued
	OnTokenIssued(ctx context.Context, authenticatable Authenticatable, tokens *TokenPair)

	// OnTokenRevoked is called when a token is revoked
	OnTokenRevoked(ctx context.Context, authenticatable Authenticatable, token string)

	// OnSessionCreated is called when a new session is created
	OnSessionCreated(ctx context.Context, authenticatable Authenticatable, session *SessionInfo)

	// OnSessionRevoked is called when a session is revoked
	OnSessionRevoked(ctx context.Context, authenticatable Authenticatable, session *SessionInfo)
}

AuthEventHooks provides hooks for authentication events Implement this interface to add custom logic (logging, audit, rate limiting, etc.)

type AuthParams

type AuthParams struct {
	UsernameOrEmail string
	Password        string
	Token           string
	Extra           map[string]any
}

AuthParams contains authentication parameters passed to strategies

func (*AuthParams) GetExtra

func (ap *AuthParams) GetExtra(key string) (any, bool)

GetExtra returns the value for a key from Extra map

func (*AuthParams) GetExtraBool

func (ap *AuthParams) GetExtraBool(key string) (bool, bool)

GetExtraBool returns a bool value from Extra map

func (*AuthParams) GetExtraInt

func (ap *AuthParams) GetExtraInt(key string) (int, bool)

GetExtraInt returns an int value from Extra map

func (*AuthParams) GetExtraString

func (ap *AuthParams) GetExtraString(key string) (string, bool)

GetExtraString returns a string value from Extra map

func (*AuthParams) Validate

func (ap *AuthParams) Validate() error

Validate checks if the AuthParams has valid data for authentication

type AuthResult

type AuthResult struct {
	Authenticatable Authenticatable
	Strategy        string
	Metadata        map[string]any // NEW: additional context from authentication
}

AuthResult contains the result of a successful authentication

type Authenticatable

type Authenticatable interface {
	GetID() string
	GetUsername() string
	GetEmail() string
	GetExtra() map[string]any
}

Authenticatable represents an authenticated entity (user, service, etc.)

type CheckRevokedFunc

type CheckRevokedFunc func(ctx context.Context, token string) bool

CheckRevokedFunc checks if a token has been revoked

type ConfigError

type ConfigError struct {
	Msg string
	Err error
}

ConfigError indicates misconfiguration or missing required setup.

func (*ConfigError) Error

func (e *ConfigError) Error() string

func (*ConfigError) Unwrap

func (e *ConfigError) Unwrap() error

type ConvertAccessTokenClaimsFunc

type ConvertAccessTokenClaimsFunc func(ctx context.Context, claims *TokenClaims) (Authenticatable, error)

ConvertAccessTokenClaimsFunc converts token claims to an Authenticatable entity

type ConvertClaimsFunc

type ConvertClaimsFunc func(ctx context.Context, claims *TokenClaims) (Authenticatable, error)

ConvertClaimsFunc converts token claims to an Authenticatable

type CredentialError

type CredentialError struct {
	Msg string
	Err error
}

CredentialError indicates a problem with user-provided credentials such as invalid username/password.

func (*CredentialError) Error

func (e *CredentialError) Error() string

func (*CredentialError) Unwrap

func (e *CredentialError) Unwrap() error

type DefaultTokenIssuer

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

DefaultTokenIssuer is a basic implementation of TokenIssuer For multi-session support, use SessionAwareTokenIssuer instead

func NewDefaultTokenIssuer

func NewDefaultTokenIssuer(secret string) *DefaultTokenIssuer

NewDefaultTokenIssuer creates a new DefaultTokenIssuer with sensible defaults

func (*DefaultTokenIssuer) ConvertAccessTokenClaims

func (ti *DefaultTokenIssuer) ConvertAccessTokenClaims(ctx context.Context, claims *TokenClaims) (Authenticatable, error)

ConvertAccessTokenClaims converts token claims to an Authenticatable entity

func (*DefaultTokenIssuer) ConvertAccessTokenClaimsWith

func (ti *DefaultTokenIssuer) ConvertAccessTokenClaimsWith(convertAccessTokenClaimsWith ConvertAccessTokenClaimsFunc)

ConvertAccessTokenClaimsWith sets the callback for converting claims to Authenticatable

func (*DefaultTokenIssuer) CreateAccessToken

func (ti *DefaultTokenIssuer) CreateAccessToken(ctx context.Context, authenticatable Authenticatable) (*Token, error)

CreateAccessToken creates a new JWT access token

func (*DefaultTokenIssuer) CreateRefreshToken

func (ti *DefaultTokenIssuer) CreateRefreshToken(ctx context.Context, authenticatable Authenticatable, oldToken *string) (*Token, error)

CreateRefreshToken creates a new refresh token oldToken is the previous refresh token being rotated (nil for initial login)

func (*DefaultTokenIssuer) DecodeAccessToken

func (ti *DefaultTokenIssuer) DecodeAccessToken(ctx context.Context, token string) (*TokenClaims, error)

DecodeAccessToken parses and validates a JWT access token

func (*DefaultTokenIssuer) RevokeRefreshToken

func (ti *DefaultTokenIssuer) RevokeRefreshToken(ctx context.Context, token string) error

RevokeRefreshToken revokes a refresh token

func (*DefaultTokenIssuer) RevokeRefreshTokenWith

func (ti *DefaultTokenIssuer) RevokeRefreshTokenWith(revokeRefreshTokenWith RevokeRefreshTokenFunc)

RevokeRefreshTokenWith sets the callback for revoking refresh tokens

func (*DefaultTokenIssuer) SetAccessTokenExpiresIn

func (ti *DefaultTokenIssuer) SetAccessTokenExpiresIn(expiresIn time.Duration)

SetAccessTokenExpiresIn sets the access token expiration duration

func (*DefaultTokenIssuer) SetAudience

func (ti *DefaultTokenIssuer) SetAudience(audience []string)

SetAudience sets the JWT audience claim

func (*DefaultTokenIssuer) SetExtraClaimsWith

func (ti *DefaultTokenIssuer) SetExtraClaimsWith(setExtraClaimsWith SetExtraClaimsFunc)

SetExtraClaimsWith sets the callback for adding extra claims to access tokens

func (*DefaultTokenIssuer) SetIssuer

func (ti *DefaultTokenIssuer) SetIssuer(issuer string)

SetIssuer sets the JWT issuer claim

func (*DefaultTokenIssuer) SetRefreshTokenExpiresIn

func (ti *DefaultTokenIssuer) SetRefreshTokenExpiresIn(expiresIn time.Duration)

SetRefreshTokenExpiresIn sets the refresh token expiration duration

func (*DefaultTokenIssuer) SetRegisteredClaimsWith

func (ti *DefaultTokenIssuer) SetRegisteredClaimsWith(setRegisteredClaimsWith SetRegisteredClaimsFunc)

SetRegisteredClaimsWith sets the callback for customizing registered claims

func (*DefaultTokenIssuer) SetSecret

func (ti *DefaultTokenIssuer) SetSecret(secret string)

SetSecret sets the JWT signing secret

func (*DefaultTokenIssuer) StoreRefreshTokenWith

func (ti *DefaultTokenIssuer) StoreRefreshTokenWith(storeRefreshTokenWith StoreRefreshTokenFunc)

StoreRefreshTokenWith sets the callback for storing refresh tokens

func (*DefaultTokenIssuer) ValidateRefreshToken

func (ti *DefaultTokenIssuer) ValidateRefreshToken(ctx context.Context, token string) (Authenticatable, error)

ValidateRefreshToken validates a refresh token and returns the associated user

func (*DefaultTokenIssuer) ValidateRefreshTokenWith

func (ti *DefaultTokenIssuer) ValidateRefreshTokenWith(validateRefreshTokenWith ValidateRefreshTokenFunc)

ValidateRefreshTokenWith sets the callback for validating refresh tokens

type ECDSAKeyProvider

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

ECDSAKeyProvider implements KeyProvider for ECDSA-based signing (ES256, ES384, ES512)

func NewECDSAKeyProvider

func NewECDSAKeyProvider(privateKey *ecdsa.PrivateKey, publicKey *ecdsa.PublicKey, method SigningMethod) (*ECDSAKeyProvider, error)

NewECDSAKeyProvider creates a new ECDSA key provider privateKey is required for signing, publicKey is required for verification If only verification is needed, privateKey can be nil

func (*ECDSAKeyProvider) Algorithm

func (p *ECDSAKeyProvider) Algorithm() SigningMethod

func (*ECDSAKeyProvider) Method

func (p *ECDSAKeyProvider) Method() jwt.SigningMethod

func (*ECDSAKeyProvider) SignKey

func (p *ECDSAKeyProvider) SignKey() any

func (*ECDSAKeyProvider) VerifyKey

func (p *ECDSAKeyProvider) VerifyKey() any

type ErrorResponse

type ErrorResponse struct {
	Status     int               `json:"status"`
	Code       string            `json:"code"`
	Message    string            `json:"message"`
	Fields     map[string]string `json:"fields,omitempty"`      // For validation errors
	RetryAfter int               `json:"retry_after,omitempty"` // For rate limit errors (seconds)
}

ErrorResponse represents a structured HTTP error response

func ErrorResponseForError

func ErrorResponseForError(err error) ErrorResponse

ErrorResponseForError creates a structured error response from an error

type ExtractSessionMetadataFunc

type ExtractSessionMetadataFunc func(ctx context.Context) map[string]any

ExtractSessionMetadataFunc extracts session metadata from context (device, IP, etc.)

type GenerateSessionIDFunc

type GenerateSessionIDFunc func(ctx context.Context) string

GenerateSessionIDFunc generates a unique session ID

type GetHashedPasswordFunc

type GetHashedPasswordFunc func(user Authenticatable) string

GetHashedPasswordFunc retrieves the hashed password from an Authenticatable Used when password validation is enabled

type GetSessionFunc

type GetSessionFunc func(ctx context.Context, token string) (*SessionInfo, error)

GetSessionFunc gets session info by refresh token

type GoAuth

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

GoAuth is the main orchestrator for authentication and token management

func GetInstance

func GetInstance() *GoAuth

GetInstance returns the registered package-wide GoAuth instance, or nil if no instance has been registered.

func New

func New() *GoAuth

New creates a new GoAuth instance

func (*GoAuth) Authenticate

func (ga *GoAuth) Authenticate(ctx context.Context, strategy string, params AuthParams) (*AuthResult, error)

Authenticate authenticates using the specified strategy

func (*GoAuth) AuthenticateAndIssueTokenPair

func (ga *GoAuth) AuthenticateAndIssueTokenPair(ctx context.Context, strategy string, params AuthParams) (*AuthResult, *TokenPair, error)

AuthenticateAndIssueTokenPair authenticates and issues tokens as a TokenPair

func (*GoAuth) AuthenticateAndIssueTokens

func (ga *GoAuth) AuthenticateAndIssueTokens(ctx context.Context, strategy string, params AuthParams) (authResult *AuthResult, accessToken *Token, refreshToken *Token, err error)

AuthenticateAndIssueTokens authenticates and issues tokens in one call Returns individual tokens (for backward compatibility)

func (*GoAuth) GetTokenIssuer

func (ga *GoAuth) GetTokenIssuer() TokenIssuer

GetTokenIssuer returns the current token issuer

func (*GoAuth) HasStrategy

func (ga *GoAuth) HasStrategy(name string) bool

HasStrategy checks if a strategy is registered

func (*GoAuth) IssueTokenPair

func (ga *GoAuth) IssueTokenPair(ctx context.Context, authenticatable Authenticatable) (*TokenPair, error)

IssueTokenPair creates access and refresh tokens as a TokenPair

func (*GoAuth) IssueTokens

func (ga *GoAuth) IssueTokens(ctx context.Context, authenticatable Authenticatable) (accessToken *Token, refreshToken *Token, err error)

IssueTokens creates access and refresh tokens for an authenticated entity Returns individual tokens (for backward compatibility)

func (*GoAuth) ListSessions

func (ga *GoAuth) ListSessions(ctx context.Context, authenticatable Authenticatable) ([]*SessionInfo, error)

ListSessions lists all active sessions for an authenticated entity Only works if the token issuer implements SessionAwareTokenIssuer

func (*GoAuth) ListStrategies

func (ga *GoAuth) ListStrategies() []string

ListStrategies returns the names of all registered strategies

func (*GoAuth) RefreshToken

func (ga *GoAuth) RefreshToken(ctx context.Context, token string) (accessToken *Token, refreshToken *Token, err error)

RefreshToken validates the old refresh token and issues new tokens Returns individual tokens (for backward compatibility)

func (*GoAuth) RefreshTokenPair

func (ga *GoAuth) RefreshTokenPair(ctx context.Context, token string) (*TokenPair, error)

RefreshTokenPair validates the old refresh token and issues new tokens as a TokenPair

func (*GoAuth) RegisterSingleton

func (ga *GoAuth) RegisterSingleton()

RegisterSingleton sets the current GoAuth as the package-wide instance. It overwrites any previously registered instance.

func (*GoAuth) RegisterSingletonOnce

func (ga *GoAuth) RegisterSingletonOnce() error

RegisterSingletonOnce sets the singleton only if it hasn't been set yet. Returns an error if an instance is already registered and differs from ga.

func (*GoAuth) RegisterStrategy

func (ga *GoAuth) RegisterStrategy(strategy Strategy)

RegisterStrategy registers an authentication strategy If a strategy with the same name already exists, it will not be replaced

func (*GoAuth) RevokeAllTokens

func (ga *GoAuth) RevokeAllTokens(ctx context.Context, authenticatable Authenticatable) error

RevokeAllTokens revokes all sessions for an authenticated entity Only works if the token issuer implements SessionAwareTokenIssuer

func (*GoAuth) RevokeSession

func (ga *GoAuth) RevokeSession(ctx context.Context, authenticatable Authenticatable, sessionID string) error

RevokeSession revokes a specific session by ID Only works if the token issuer implements SessionAwareTokenIssuer

func (*GoAuth) RevokeToken

func (ga *GoAuth) RevokeToken(ctx context.Context, token string) error

RevokeToken revokes a refresh token

func (*GoAuth) SetEventHooks

func (ga *GoAuth) SetEventHooks(hooks AuthEventHooks)

SetEventHooks sets the event hooks for authentication events

func (*GoAuth) SetTokenIssuer

func (ga *GoAuth) SetTokenIssuer(tokenIssuer TokenIssuer)

SetTokenIssuer sets the token issuer for the GoAuth instance

func (*GoAuth) UnregisterStrategy

func (ga *GoAuth) UnregisterStrategy(name string) error

UnregisterStrategy removes a registered strategy by name

type HMACKeyProvider

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

HMACKeyProvider implements KeyProvider for HMAC-based signing (HS256, HS384, HS512)

func NewHMACKeyProvider

func NewHMACKeyProvider(secret []byte, method SigningMethod) (*HMACKeyProvider, error)

NewHMACKeyProvider creates a new HMAC key provider

func (*HMACKeyProvider) Algorithm

func (p *HMACKeyProvider) Algorithm() SigningMethod

func (*HMACKeyProvider) Method

func (p *HMACKeyProvider) Method() jwt.SigningMethod

func (*HMACKeyProvider) SignKey

func (p *HMACKeyProvider) SignKey() any

func (*HMACKeyProvider) VerifyKey

func (p *HMACKeyProvider) VerifyKey() any

type InternalError

type InternalError struct {
	Msg string
	Err error
}

InternalError indicates an unexpected internal failure (e.g., IO/DB/signing).

func (*InternalError) Error

func (e *InternalError) Error() string

func (*InternalError) Unwrap

func (e *InternalError) Unwrap() error

type JWTStrategy

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

JWTStrategy implements JWT token-based authentication

func NewJWTStrategy

func NewJWTStrategy(tokenIssuer TokenIssuer) *JWTStrategy

NewJWTStrategy creates a new JWTStrategy with the given token issuer

func (*JWTStrategy) Authenticate

func (js *JWTStrategy) Authenticate(ctx context.Context, params AuthParams) (Authenticatable, error)

Authenticate authenticates using a JWT token

func (*JWTStrategy) GetTokenIssuer

func (js *JWTStrategy) GetTokenIssuer() TokenIssuer

GetTokenIssuer returns the underlying token issuer Deprecated: Access TokenIssuer directly

func (*JWTStrategy) Name

func (js *JWTStrategy) Name() string

Name returns the strategy name

func (*JWTStrategy) SetTokenIssuer

func (js *JWTStrategy) SetTokenIssuer(ti TokenIssuer)

SetTokenIssuer sets the token issuer (for backward compatibility) Deprecated: Use NewJWTStrategy instead

func (*JWTStrategy) WithClaimsConverter

func (js *JWTStrategy) WithClaimsConverter(convert ConvertClaimsFunc) *JWTStrategy

WithClaimsConverter sets a custom claims to Authenticatable converter This overrides the TokenIssuer's ConvertAccessTokenClaims

func (*JWTStrategy) WithExpectedType

func (js *JWTStrategy) WithExpectedType(tokenType TokenType) *JWTStrategy

WithExpectedType sets the expected token type When set, the strategy will reject tokens that don't match

func (*JWTStrategy) WithName

func (js *JWTStrategy) WithName(name string) *JWTStrategy

WithName sets a custom name for the strategy

func (*JWTStrategy) WithRevocationCheck

func (js *JWTStrategy) WithRevocationCheck(check CheckRevokedFunc) *JWTStrategy

WithRevocationCheck sets the revocation check function

type KeyProvider

type KeyProvider interface {
	// Method returns the JWT signing method
	Method() jwt.SigningMethod
	// SignKey returns the key used for signing tokens
	SignKey() any
	// VerifyKey returns the key used for verifying tokens
	VerifyKey() any
	// Algorithm returns the signing method name
	Algorithm() SigningMethod
}

KeyProvider abstracts the signing key management for JWT tokens

type ListSessionsFunc

type ListSessionsFunc func(ctx context.Context, auth Authenticatable) ([]*SessionInfo, error)

ListSessionsFunc lists all active sessions for a user

type LocalStrategy

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

LocalStrategy implements username/password authentication

func NewLocalStrategy

func NewLocalStrategy(lookupUser LookupUserFunc) *LocalStrategy

NewLocalStrategy creates a new LocalStrategy with the given lookup function

func (*LocalStrategy) Authenticate

func (ls *LocalStrategy) Authenticate(ctx context.Context, params AuthParams) (Authenticatable, error)

Authenticate authenticates a user with username/email and password

func (*LocalStrategy) Name

func (ls *LocalStrategy) Name() string

Name returns the strategy name

func (*LocalStrategy) SetLookupUser

func (ls *LocalStrategy) SetLookupUser(fn LookupUserFunc)

LookupUserWith is kept for backward compatibility Deprecated: Use NewLocalStrategy instead

func (*LocalStrategy) WithName

func (ls *LocalStrategy) WithName(name string) *LocalStrategy

WithName sets a custom name for the strategy

func (*LocalStrategy) WithPasswordValidator

func (ls *LocalStrategy) WithPasswordValidator(validate ValidatePasswordFunc, getHashed GetHashedPasswordFunc) *LocalStrategy

WithPasswordValidator sets the password validation function When set, the strategy will validate the password from AuthParams against the hashed password retrieved via GetHashedPassword

func (*LocalStrategy) WithRateLimiter

func (ls *LocalStrategy) WithRateLimiter(check RateLimitCheckFunc, record RecordAttemptFunc) *LocalStrategy

WithRateLimiter sets the rate limiting functions

func (*LocalStrategy) WithUsernameNormalizer

func (ls *LocalStrategy) WithUsernameNormalizer(normalize NormalizeUsernameFunc) *LocalStrategy

WithUsernameNormalizer sets a custom username normalization function

type LookupUserFunc

type LookupUserFunc func(ctx context.Context, params AuthParams) (Authenticatable, error)

LookupUserFunc looks up a user by credentials and returns an Authenticatable The returned user should have a hashed password available if password validation is used

type NoOpEventHooks

type NoOpEventHooks struct{}

NoOpEventHooks is a default implementation of AuthEventHooks that does nothing Embed this in your custom hooks to only override the methods you need

func (*NoOpEventHooks) OnAfterAuthenticate

func (h *NoOpEventHooks) OnAfterAuthenticate(ctx context.Context, strategy string, result *AuthResult, err error)

func (*NoOpEventHooks) OnBeforeAuthenticate

func (h *NoOpEventHooks) OnBeforeAuthenticate(ctx context.Context, strategy string, params AuthParams) error

func (*NoOpEventHooks) OnSessionCreated

func (h *NoOpEventHooks) OnSessionCreated(ctx context.Context, authenticatable Authenticatable, session *SessionInfo)

func (*NoOpEventHooks) OnSessionRevoked

func (h *NoOpEventHooks) OnSessionRevoked(ctx context.Context, authenticatable Authenticatable, session *SessionInfo)

func (*NoOpEventHooks) OnTokenIssued

func (h *NoOpEventHooks) OnTokenIssued(ctx context.Context, authenticatable Authenticatable, tokens *TokenPair)

func (*NoOpEventHooks) OnTokenRevoked

func (h *NoOpEventHooks) OnTokenRevoked(ctx context.Context, authenticatable Authenticatable, token string)

type NormalizeUsernameFunc

type NormalizeUsernameFunc func(username string) string

NormalizeUsernameFunc normalizes a username (e.g., trim whitespace, lowercase)

type NotFoundError

type NotFoundError struct {
	Msg string
	Err error
}

NotFoundError indicates a required element was not found (e.g., strategy).

func (*NotFoundError) Error

func (e *NotFoundError) Error() string

func (*NotFoundError) Unwrap

func (e *NotFoundError) Unwrap() error

type PasswordValidator

type PasswordValidator interface {
	// ValidatePassword checks if the plain password matches the hashed password
	ValidatePassword(plain, hashed string) bool
}

PasswordValidator defines the contract for password validation

type PasswordValidatorFunc

type PasswordValidatorFunc func(plain, hashed string) bool

PasswordValidatorFunc is a function adapter for PasswordValidator

func (PasswordValidatorFunc) ValidatePassword

func (f PasswordValidatorFunc) ValidatePassword(plain, hashed string) bool

type RSAKeyProvider

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

RSAKeyProvider implements KeyProvider for RSA-based signing (RS256, RS384, RS512)

func NewRSAKeyProvider

func NewRSAKeyProvider(privateKey *rsa.PrivateKey, publicKey *rsa.PublicKey, method SigningMethod) (*RSAKeyProvider, error)

NewRSAKeyProvider creates a new RSA key provider privateKey is required for signing, publicKey is required for verification If only verification is needed, privateKey can be nil

func (*RSAKeyProvider) Algorithm

func (p *RSAKeyProvider) Algorithm() SigningMethod

func (*RSAKeyProvider) Method

func (p *RSAKeyProvider) Method() jwt.SigningMethod

func (*RSAKeyProvider) SignKey

func (p *RSAKeyProvider) SignKey() any

func (*RSAKeyProvider) VerifyKey

func (p *RSAKeyProvider) VerifyKey() any

type RateLimitCheckFunc

type RateLimitCheckFunc func(ctx context.Context, identifier string) error

RateLimitCheckFunc checks if an authentication attempt should be rate limited Returns nil if allowed, RateLimitError if exceeded

type RateLimitError

type RateLimitError struct {
	Msg        string
	RetryAfter time.Duration
	Err        error
}

RateLimitError indicates that rate limit has been exceeded.

func (*RateLimitError) Error

func (e *RateLimitError) Error() string

func (*RateLimitError) Unwrap

func (e *RateLimitError) Unwrap() error

type RateLimiter

type RateLimiter interface {
	// CheckRateLimit checks if the authentication attempt is allowed
	// Returns nil if allowed, RateLimitError if exceeded
	CheckRateLimit(ctx context.Context, identifier string) error

	// RecordAttempt records an authentication attempt (success or failure)
	RecordAttempt(ctx context.Context, identifier string, success bool)
}

RateLimiter defines the contract for rate limiting authentication attempts

type RecordAttemptFunc

type RecordAttemptFunc func(ctx context.Context, identifier string, success bool)

RecordAttemptFunc records an authentication attempt for rate limiting

type RevokeAllSessionsFunc

type RevokeAllSessionsFunc func(ctx context.Context, auth Authenticatable) error

RevokeAllSessionsFunc revokes all sessions for a user

type RevokeRefreshTokenFunc

type RevokeRefreshTokenFunc func(ctx context.Context, token string) error

RevokeRefreshTokenFunc revokes a refresh token

type RevokeSessionFunc

type RevokeSessionFunc func(ctx context.Context, auth Authenticatable, sessionID string) error

RevokeSessionFunc revokes a specific session

type SessionAwareTokenIssuer

type SessionAwareTokenIssuer interface {
	TokenIssuer

	// GetSession returns session information for a refresh token
	GetSession(ctx context.Context, token string) (*SessionInfo, error)

	// RevokeSession revokes a specific session by ID
	RevokeSession(ctx context.Context, authenticatable Authenticatable, sessionID string) error

	// RevokeAllSessions revokes all sessions for an authenticated entity
	RevokeAllSessions(ctx context.Context, authenticatable Authenticatable) error

	// ListSessions returns all active sessions for an authenticated entity
	ListSessions(ctx context.Context, authenticatable Authenticatable) ([]*SessionInfo, error)
}

SessionAwareTokenIssuer extends TokenIssuer with session management capabilities

type SessionError

type SessionError struct {
	Msg       string
	SessionID string
	Err       error
}

SessionError indicates session-related problems.

func (*SessionError) Error

func (e *SessionError) Error() string

func (*SessionError) Unwrap

func (e *SessionError) Unwrap() error

type SessionInfo

type SessionInfo struct {
	ID        string
	UserID    string
	CreatedAt time.Time
	ExpiresAt time.Time
	Metadata  map[string]any // device, IP, user agent, location, etc.
}

SessionInfo contains session metadata for multi-session support

func (*SessionInfo) GetMetadata

func (s *SessionInfo) GetMetadata(key string) (any, bool)

GetMetadata returns a value from session metadata

func (*SessionInfo) GetMetadataString

func (s *SessionInfo) GetMetadataString(key string) (string, bool)

GetMetadataString returns a string value from session metadata

func (*SessionInfo) IsExpired

func (s *SessionInfo) IsExpired() bool

IsExpired checks if the session has expired

type SessionTokenIssuer

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

SessionTokenIssuer implements TokenIssuer and SessionAwareTokenIssuer interfaces with full multi-session support and configurable signing methods

func (*SessionTokenIssuer) ConvertAccessTokenClaims

func (ti *SessionTokenIssuer) ConvertAccessTokenClaims(ctx context.Context, claims *TokenClaims) (Authenticatable, error)

ConvertAccessTokenClaims converts token claims to an Authenticatable entity

func (*SessionTokenIssuer) CreateAccessToken

func (ti *SessionTokenIssuer) CreateAccessToken(ctx context.Context, auth Authenticatable) (*Token, error)

CreateAccessToken creates a new JWT access token with session ID

func (*SessionTokenIssuer) CreateAccessTokenWithSession

func (ti *SessionTokenIssuer) CreateAccessTokenWithSession(ctx context.Context, auth Authenticatable, sessionID string) (*Token, error)

CreateAccessTokenWithSession creates a new JWT access token with a specific session ID

func (*SessionTokenIssuer) CreateRefreshToken

func (ti *SessionTokenIssuer) CreateRefreshToken(ctx context.Context, auth Authenticatable, oldToken *string) (*Token, error)

CreateRefreshToken creates a new refresh token with session

func (*SessionTokenIssuer) DecodeAccessToken

func (ti *SessionTokenIssuer) DecodeAccessToken(ctx context.Context, tokenStr string) (*TokenClaims, error)

DecodeAccessToken parses and validates a JWT access token

func (*SessionTokenIssuer) GetSession

func (ti *SessionTokenIssuer) GetSession(ctx context.Context, token string) (*SessionInfo, error)

GetSession returns session information for a refresh token

func (*SessionTokenIssuer) IssueTokenPair

func (ti *SessionTokenIssuer) IssueTokenPair(ctx context.Context, auth Authenticatable, oldRefreshToken *string) (*TokenPair, error)

IssueTokenPair creates both access and refresh tokens in one call This is a convenience method that ensures tokens share the same session ID

func (*SessionTokenIssuer) ListSessions

func (ti *SessionTokenIssuer) ListSessions(ctx context.Context, auth Authenticatable) ([]*SessionInfo, error)

ListSessions returns all active sessions for an authenticated entity

func (*SessionTokenIssuer) RevokeAllSessions

func (ti *SessionTokenIssuer) RevokeAllSessions(ctx context.Context, auth Authenticatable) error

RevokeAllSessions revokes all sessions for an authenticated entity

func (*SessionTokenIssuer) RevokeRefreshToken

func (ti *SessionTokenIssuer) RevokeRefreshToken(ctx context.Context, token string) error

RevokeRefreshToken revokes a refresh token by revoking its session

func (*SessionTokenIssuer) RevokeSession

func (ti *SessionTokenIssuer) RevokeSession(ctx context.Context, auth Authenticatable, sessionID string) error

RevokeSession revokes a specific session by ID

func (*SessionTokenIssuer) ValidateRefreshToken

func (ti *SessionTokenIssuer) ValidateRefreshToken(ctx context.Context, token string) (Authenticatable, error)

ValidateRefreshToken validates a refresh token and returns the associated user

type SessionTokenIssuerBuilder

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

SessionTokenIssuerBuilder provides a fluent API for building SessionTokenIssuer

func NewSessionAwareTokenIssuer

func NewSessionAwareTokenIssuer() *SessionTokenIssuerBuilder

NewSessionAwareTokenIssuer creates a new builder for SessionTokenIssuer

func (*SessionTokenIssuerBuilder) Build

Build creates the SessionTokenIssuer, returning any configuration errors

func (*SessionTokenIssuerBuilder) WithAccessTokenTTL

WithAccessTokenTTL sets the access token time-to-live

func (*SessionTokenIssuerBuilder) WithAudience

func (b *SessionTokenIssuerBuilder) WithAudience(audience []string) *SessionTokenIssuerBuilder

WithAudience sets the JWT audience claim

func (*SessionTokenIssuerBuilder) WithClaimsConverter

WithClaimsConverter sets the claims to Authenticatable converter

func (*SessionTokenIssuerBuilder) WithExtraClaims

WithExtraClaims sets the extra claims callback

func (*SessionTokenIssuerBuilder) WithGetSession

WithGetSession sets the get session callback

func (*SessionTokenIssuerBuilder) WithHMACSecret

func (b *SessionTokenIssuerBuilder) WithHMACSecret(secret []byte, method SigningMethod) *SessionTokenIssuerBuilder

WithHMACSecret configures HMAC signing with the given secret

func (*SessionTokenIssuerBuilder) WithIssuer

WithIssuer sets the JWT issuer claim

func (*SessionTokenIssuerBuilder) WithKeyProvider

WithKeyProvider sets a custom key provider

func (*SessionTokenIssuerBuilder) WithListSessions

WithListSessions sets the list sessions callback

func (*SessionTokenIssuerBuilder) WithRSAKeys

func (b *SessionTokenIssuerBuilder) WithRSAKeys(privateKey *rsa.PrivateKey, publicKey *rsa.PublicKey, method SigningMethod) *SessionTokenIssuerBuilder

WithRSAKeys configures RSA signing with the given keys

func (*SessionTokenIssuerBuilder) WithRefreshTokenTTL

WithRefreshTokenTTL sets the refresh token time-to-live

func (*SessionTokenIssuerBuilder) WithRegisteredClaims

WithRegisteredClaims sets the registered claims callback

func (*SessionTokenIssuerBuilder) WithSessionIDGenerator

WithSessionIDGenerator sets a custom session ID generator

func (*SessionTokenIssuerBuilder) WithSessionMetadataExtractor

WithSessionMetadataExtractor sets a custom session metadata extractor

func (*SessionTokenIssuerBuilder) WithSessionStore

WithSessionStore sets the session storage callbacks

type SetExtraClaimsFunc

type SetExtraClaimsFunc func(ctx context.Context, authenticatable Authenticatable) map[string]any

SetExtraClaimsFunc returns extra claims to include in the access token

type SetRegisteredClaimsFunc

type SetRegisteredClaimsFunc func(ctx context.Context, authenticatable Authenticatable) jwt.RegisteredClaims

SetRegisteredClaimsFunc returns custom registered claims for the access token

type SigningMethod

type SigningMethod string

SigningMethod represents supported JWT signing algorithms

const (
	// HMAC signing methods (symmetric)
	HS256 SigningMethod = "HS256"
	HS384 SigningMethod = "HS384"
	HS512 SigningMethod = "HS512"

	// RSA signing methods (asymmetric)
	RS256 SigningMethod = "RS256"
	RS384 SigningMethod = "RS384"
	RS512 SigningMethod = "RS512"

	// ECDSA signing methods (asymmetric)
	ES256 SigningMethod = "ES256"
	ES384 SigningMethod = "ES384"
	ES512 SigningMethod = "ES512"
)

type StoreRefreshTokenFunc

type StoreRefreshTokenFunc func(ctx context.Context, authenticatable Authenticatable, token *Token, oldToken *string) error

StoreRefreshTokenFunc stores a refresh token oldToken is the previous refresh token being rotated (nil for initial login)

type StoreSessionFunc

type StoreSessionFunc func(ctx context.Context, auth Authenticatable, session *SessionInfo, token *Token, oldToken *string) error

StoreSessionFunc stores a session and its refresh token oldToken is the previous refresh token being rotated (nil for initial login)

type Strategy

type Strategy interface {
	Name() string
	Authenticate(ctx context.Context, params AuthParams) (Authenticatable, error)
}

Strategy defines the authentication strategy interface

type Token

type Token struct {
	Value     string
	Type      TokenType
	ExpiresIn time.Duration
	IssuedAt  time.Time
	SessionID string // For multi-session support
}

Token represents an authentication token (access or refresh)

type TokenClaims

type TokenClaims struct {
	jwt.RegisteredClaims
	Username    string         `json:"username,omitempty"`
	Email       string         `json:"email,omitempty"`
	TokenType   TokenType      `json:"typ,omitempty"` // "access" or "refresh"
	SessionID   string         `json:"sid,omitempty"` // Session identifier for multi-session support
	ExtraClaims map[string]any `json:"ext,omitempty"`
}

TokenClaims represents the JWT claims for access tokens

func (*TokenClaims) GetExtraClaim

func (tc *TokenClaims) GetExtraClaim(key string) (any, bool)

GetExtraClaim returns a value from extra claims

func (*TokenClaims) GetExtraClaimBool

func (tc *TokenClaims) GetExtraClaimBool(key string) (bool, bool)

GetExtraClaimBool returns a bool value from extra claims

func (*TokenClaims) GetExtraClaimString

func (tc *TokenClaims) GetExtraClaimString(key string) (string, bool)

GetExtraClaimString returns a string value from extra claims

func (*TokenClaims) IsAccessToken

func (tc *TokenClaims) IsAccessToken() bool

IsAccessToken returns true if this is an access token

func (*TokenClaims) IsRefreshToken

func (tc *TokenClaims) IsRefreshToken() bool

IsRefreshToken returns true if this is a refresh token

type TokenError

type TokenError struct {
	Msg string
	Err error
}

TokenError indicates problems related to tokens (missing/invalid/expired).

func (*TokenError) Error

func (e *TokenError) Error() string

func (*TokenError) Unwrap

func (e *TokenError) Unwrap() error

type TokenIssuer

type TokenIssuer interface {
	// CreateAccessToken generates a new access token for the authenticated entity
	CreateAccessToken(ctx context.Context, authenticatable Authenticatable) (*Token, error)

	// CreateRefreshToken generates a new refresh token
	// oldToken is the previous refresh token being rotated (nil for initial login)
	CreateRefreshToken(ctx context.Context, authenticatable Authenticatable, oldToken *string) (*Token, error)

	// DecodeAccessToken parses and validates an access token, returning its claims
	DecodeAccessToken(ctx context.Context, token string) (*TokenClaims, error)

	// ConvertAccessTokenClaims converts token claims back to an Authenticatable entity
	ConvertAccessTokenClaims(ctx context.Context, claims *TokenClaims) (Authenticatable, error)

	// ValidateRefreshToken validates a refresh token and returns the associated entity
	ValidateRefreshToken(ctx context.Context, token string) (Authenticatable, error)

	// RevokeRefreshToken invalidates a refresh token
	RevokeRefreshToken(ctx context.Context, token string) error
}

TokenIssuer defines the contract for token creation and validation

type TokenPair

type TokenPair struct {
	Access  *Token
	Refresh *Token
}

TokenPair contains both access and refresh tokens

type TokenRevoker

type TokenRevoker interface {
	// IsRevoked checks if a token has been revoked
	IsRevoked(ctx context.Context, token string) bool

	// Revoke marks a token as revoked
	Revoke(ctx context.Context, token string) error
}

TokenRevoker defines the contract for checking token revocation

type TokenType

type TokenType string

TokenType represents the type of token (access or refresh)

const (
	AccessToken  TokenType = "access"
	RefreshToken TokenType = "refresh"
)

type User

type User struct {
	ID       string
	Username string
	Email    string
	Extra    map[string]any
}

User is a default implementation of Authenticatable

func (*User) GetEmail

func (u *User) GetEmail() string

func (*User) GetExtra

func (u *User) GetExtra() map[string]any

func (*User) GetID

func (u *User) GetID() string

func (*User) GetUsername

func (u *User) GetUsername() string

type ValidatePasswordFunc

type ValidatePasswordFunc func(plain, hashed string) bool

ValidatePasswordFunc validates a plain password against a hashed password

type ValidateRefreshTokenFunc

type ValidateRefreshTokenFunc func(ctx context.Context, token string) (Authenticatable, error)

ValidateRefreshTokenFunc validates a refresh token and returns the associated user

type ValidateSessionFunc

type ValidateSessionFunc func(ctx context.Context, token string) (Authenticatable, *SessionInfo, error)

ValidateSessionFunc validates a refresh token and returns the user and session

type ValidationError

type ValidationError struct {
	Msg    string
	Fields map[string]string // field name -> error message
	Err    error
}

ValidationError indicates validation failure on input parameters.

func (*ValidationError) Error

func (e *ValidationError) Error() string

func (*ValidationError) GetFieldError

func (e *ValidationError) GetFieldError(field string) (string, bool)

GetFieldError returns the error message for a specific field

func (*ValidationError) Unwrap

func (e *ValidationError) Unwrap() error

Directories

Path Synopsis
http_server command

Jump to

Keyboard shortcuts

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