Stateless Guard (JWT/PASETO)

Stateless authentication uses self-contained tokens (JWT or PASETO) to carry user identity. This allows the server to verify the user without querying the database or cache on every request, making it ideal for distributed systems and mobile apps.

Concept

When a user logs in, the server generates a signed token. The client stores this token (e.g., in localStorage or a secure cookie) and sends it in the Authorization: Bearer <token> header for subsequent requests. The server verifies the signature and extracts the user ID from the token payload.

Configuration

Configure the stateless guard in your config/auth.go and populate settings via .env:

AUTH_TOKEN_DRIVER=paseto    # jwt or paseto
AUTH_TOKEN_SECRET=your-32-character-secret
AUTH_TOKEN_EXPIRES_IN=24h

Drivers

JWT Driver

Industry standard. Uses HMAC-SHA256 (HS256) for signing. Widely compatible but requires careful secret management.

PASETO Driver

Modern, secure-by-default alternative (V4 Local). Avoids common JWT pitfalls like "alg: none" or algorithm confusion.

Setup

Initialize the guard in your application boot process (e.g., bin/server.go):

func bootStatelessAuth(app *nimbus.App) {
    var driver auth.TokenDriver
    if config.Auth.Stateless.Driver == "paseto" {
        driver = auth.NewPasetoDriver(config.Auth.Stateless.Secret)
    } else {
        driver = auth.NewJWTDriver(config.Auth.Stateless.Secret)
    }

    // UserLoader is used only after token validation to load the actual model from DB
    guard := auth.NewStatelessGuard(driver, models.UserByID(database.DB))

    app.Container.Singleton("auth.stateless", func() *auth.StatelessGuard {
        return guard
    })
}

Usage

Generating Tokens

guard := app.Container.MustMake("auth.stateless").(*auth.StatelessGuard)

// Generate token for user ID 123
token, err := guard.GenerateToken("123", 24 * time.Hour)

Middleware Protection

Register the middleware in your start/kernel.go and use it on your routes:

// In kernel.go
Middleware["auth:api"] = auth.RequireStatelessToken(guard)

// In routes.go
api := app.Router.Group("/api", Middleware["auth:api"])
api.Get("/profile", ProfileHandler)

Security Best Practices

  • Use PASETO: Favor PASETO over JWT for new applications.
  • Rotate Secrets: Change your AUTH_TOKEN_SECRET regularly. Changing it will invalidate all existing tokens (global logout).
  • Short Expirations: Use short-lived tokens and implement refresh token logic for improved security.
  • Secure Storage: If storing tokens in cookies, always use HttpOnly and Secure flags.