ForgeAuth

Complete authentication system for Forge Kernel with session-based web authentication and optional JWT support for mobile and API applications.

Overview

ForgeAuth provides a complete, production-ready authentication system for Forge Kernel applications. It offers session-based authentication for traditional web applications and optional JWT (JSON Web Token) support for mobile apps and API clients. Built with simplicity, robustness, and flexibility in mind.

Key Features

Session-based web authentication
Optional JWT for mobile/API
User registration and login
Password hashing (bcrypt)
Login attempt throttling
Route protection middleware
User repository with caching
Custom JWT claims support

What ForgeAuth Provides

  • Web Authentication: Session-based authentication for traditional web applications. Users log in with credentials, and sessions are managed automatically.
  • API/Mobile Authentication: Optional JWT support for mobile applications and API clients. JWT is opt-in via configuration — not enabled by default.
  • User Management: Complete user registration, login, logout, and user data management with repository pattern.
  • Security Features: Password hashing with bcrypt, login attempt throttling, session regeneration, and secure token handling.
  • Middleware Protection: Easy-to-use middleware for protecting routes — AuthMiddleware for web, ApiJwtMiddleware for API.
  • Validation: Built-in validation helpers for login and registration forms.
  • Flexible Architecture: Service-based design with clear separation between web and API authentication flows.

Simple Yet Powerful: ForgeAuth is designed to be simple to use while providing robust security features. Web authentication works out of the box with no configuration. JWT support is available when you need it, but it's opt-in so you're not forced to use it.

Architecture & Design Philosophy

ForgeAuth is built with a clear separation of concerns and a focus on simplicity without sacrificing power or security.

Why It's Built This Way

ForgeAuth follows a service-based architecture that separates authentication logic from controllers and routes. This design provides:

  • Simplicity: Easy to use with minimal boilerplate. Web authentication works immediately after installation.
  • Robustness: Built-in security features like login throttling, password hashing, and session management.
  • Flexibility: Web sessions by default, JWT opt-in for mobile. Use what you need, when you need it.
  • Power: Full user management, relationships, caching, and extensibility through custom claims.

Separation of Concerns

ForgeAuth clearly separates web and API authentication:

Web Authentication

Session-based, works out of the box

  • • Uses PHP sessions
  • • Automatic session management
  • AuthMiddleware for protection
  • WebLoginController for routes

API/Mobile Authentication

JWT-based, opt-in via configuration

  • • JWT tokens (access + refresh)
  • • Stateless authentication
  • ApiJwtMiddleware for protection
  • ApiLoginController for routes

Opt-In JWT Design

JWT support is opt-in, not enabled by default. This means:

  • Web applications work immediately without any JWT configuration
  • You only enable JWT when you need it for mobile apps or API clients
  • No unnecessary complexity for simple web applications
  • Clear separation between web and API authentication flows

Design Decision: By making JWT opt-in, ForgeAuth stays simple for web applications while still providing powerful mobile/API capabilities when needed. You're not forced to configure JWT if you only need web authentication.

Repository Pattern

User data access uses the repository pattern with built-in caching:

  • Separation of data access logic from business logic
  • Query caching for performance
  • Easy to extend and customize
  • Interface-based design for testability

Installation

Install ForgeAuth using ForgePackageManager. The module includes database migrations that will run automatically after installation.

Using ForgePackageManager

# Install with wizard (interactive)
php forge.php package:install-module

# Install directly (skip wizard)
php forge.php package:install-module --module=ForgeAuth

# Install specific version
php forge.php package:install-module --module=ForgeAuth@0.2.4

Post-Installation

After installation, ForgeAuth automatically runs database migrations to create the necessary tables:

  • users table for user accounts
  • profiles table for user profiles (optional)

Automatic Migrations: The module uses #[PostInstall] attribute to automatically run migrations after installation. No manual steps required.

Verify Installation

Verify that ForgeAuth is installed correctly:

# List installed modules
php forge.php package:list-modules | grep ForgeAuth

# Check if tables were created
php forge.php db:migrate:status

Configuration

ForgeAuth requires minimal configuration. Web authentication works out of the box. JWT support is opt-in and requires additional configuration.

Session-Based Authentication (Default)

Web authentication using PHP sessions requires no configuration. It works immediately after installation. The session configuration is handled by Forge Kernel's session system.

JWT Configuration (Opt-In)

To enable JWT support for mobile applications or API clients, add the following to your config/security.php or .env file:

// config/security.php
return [
    'jwt' => [
        'enabled' => true,  // Enable JWT support
        'secret' => env('JWT_SECRET', 'your-secret-key-here'),  // Required if enabled
        'ttl' => 900,  // Access token TTL in seconds (default: 15 minutes)
        'refresh_ttl' => 604800,  // Refresh token TTL in seconds (default: 7 days)
    ],
];
# .env file
JWT_SECRET=your-very-secure-secret-key-here-minimum-32-characters

JWT Configuration Options

  • security.jwt.enabled (default: false) — Enable or disable JWT support
  • security.jwt.secret (required if enabled) — Secret key for signing JWT tokens. Use a strong, random string.
  • security.jwt.ttl (default: 900) — Access token time-to-live in seconds (15 minutes)
  • security.jwt.refresh_ttl (default: 604800) — Refresh token time-to-live in seconds (7 days)

Security Warning: If you enable JWT, you must set a strong secret key. Use a random string of at least 32 characters. Never commit secrets to version control — use environment variables.

Login Attempt Throttling

ForgeAuth includes built-in login attempt throttling to prevent brute-force attacks. Configure it in config/security.php:

// config/security.php
return [
    'password' => [
        'max_login_attempts' => 5,  // Maximum failed login attempts
        'lockout_time' => 300,  // Lockout duration in seconds (default: 5 minutes)
    ],
];
  • security.password.max_login_attempts (default: 5) — Maximum failed login attempts before lockout
  • security.password.lockout_time (default: 300) — Lockout duration in seconds (5 minutes)

Web Authentication

Session-based authentication for traditional web applications. Works out of the box with no JWT configuration required.

Authentication Flow

Web authentication uses PHP sessions:

  1. User submits login credentials
  2. ForgeAuthService::login() validates credentials
  3. Session is regenerated for security
  4. User ID and identifier are stored in session
  5. User is redirected to protected area

Using ForgeAuthService

The ForgeAuthService provides the main authentication methods:

use App\Modules\ForgeAuth\Services\ForgeAuthService;

class MyController
{
    public function __construct(
        private readonly ForgeAuthService $authService
    ) {}

    public function login(array $credentials): Response
    {
        // Login user (throws LoginException on failure)
        $user = $this->authService->login($credentials);
        
        // Get current authenticated user
        $user = $this->authService->user();
        
        // Logout user
        $this->authService->logout();
        
        // Register new user
        $this->authService->register($credentials);
    }
}

Protecting Routes with Middleware

Use AuthMiddleware to protect routes that require authentication:

use App\Modules\ForgeAuth\Middlewares\AuthMiddleware;
use Forge\Core\Http\Attributes\Middleware;
use Forge\Core\Routing\Route;

#[Middleware("web")]
final class DashboardController
{
    #[Route("/dashboard")]
    #[Middleware("App\Modules\ForgeAuth\Middlewares\AuthMiddleware")]
    public function welcome(): Response
    {
        // This route requires authentication
        // Users will be redirected to /auth/login if not authenticated
        $user = $this->authService->user();
        
        return $this->view("pages/dashboard/index", [
            "user" => $user,
        ]);
    }
}

Registration Example

Here's a complete example of user registration from HomeController:

use App\Modules\ForgeAuth\Services\ForgeAuthService;
use App\Modules\ForgeAuth\Validation\ForgeAuthValidate;
use Forge\Core\Helpers\Flash;
use Forge\Core\Helpers\Redirect;
use Forge\Exceptions\ValidationException;

#[Route("/", "POST")]
public function register(Request $request): Response
{
    try {
        // Validate input
        ForgeAuthValidate::register($request->postData);
        
        // Sanitize input
        $credentials = $this->sanitize($request->postData);
        
        // Register user
        $this->forgeAuthService->register($credentials);
        
        Flash::set("success", "User registered successfully");
        return Redirect::to("/");
    } catch (ValidationException) {
        return Redirect::to("/");
    }
}

Login Attempt Throttling

ForgeAuth automatically throttles login attempts to prevent brute-force attacks:

  • After max_login_attempts failed attempts, the user is locked out
  • Lockout lasts for lockout_time seconds
  • Failed attempts are tracked in the session
  • Successful login resets the attempt counter

Automatic Protection: Login throttling is built into ForgeAuthService::login(). No additional configuration needed — it works automatically.

API/Mobile Authentication (JWT)

Optional JWT support for mobile applications and API clients. JWT is opt-in — enable it in configuration when you need it.

Enabling JWT

First, enable JWT in your configuration (see Configuration section). Once enabled, you can use JWT authentication for API routes and mobile applications.

JWT Token Flow

JWT authentication uses access tokens and refresh tokens:

  1. User logs in via API endpoint
  2. Server issues access token (short-lived) and refresh token (long-lived)
  3. Client includes access token in Authorization: Bearer <token> header
  4. When access token expires, client uses refresh token to get new tokens

API Login Example

Here's how API login works with JWT tokens:

use App\Modules\ForgeAuth\Services\ForgeAuthService;
use App\Modules\ForgeAuth\Validation\ForgeAuthValidate;

#[ApiRoute('/auth/login', 'POST')]
public function login(Request $request): Response
{
    try {
        $data = $request->json() ?: $request->postData;
        ForgeAuthValidate::login($data);
        $loginCredentials = $this->sanitize($data);
        
        // Login user (creates session for web, but we'll use JWT)
        $user = $this->forgeAuthService->login($loginCredentials);
        
        // Issue JWT tokens
        $tokens = $this->forgeAuthService->issueToken($user);
        
        // Returns: {
        //   "user": {...},
        //   "tokens": {
        //     "access_token": "...",
        //     "refresh_token": "...",
        //     "expires_in": 900
        //   }
        // }
        return $this->apiResponse([
            'user' => $user,
            'tokens' => $tokens,
        ]);
    } catch (LoginException $e) {
        return $this->apiError('Invalid credentials', 401);
    } catch (\RuntimeException $e) {
        return $this->apiError('JWT is not enabled', 500);
    }
}

Token Refresh

When the access token expires, use the refresh token to get new tokens:

#[ApiRoute('/auth/refresh', 'POST')]
public function refresh(Request $request): Response
{
    $data = $request->json() ?: $request->postData;
    $refreshToken = $data['refresh_token'] ?? null;
    
    if (!$refreshToken) {
        return $this->apiError('Refresh token is required', 400);
    }
    
    $tokens = $this->forgeAuthService->refreshToken($refreshToken);
    
    if (!$tokens) {
        return $this->apiError('Invalid refresh token', 401);
    }
    
    // Returns new access_token and refresh_token
    return $this->apiResponse($tokens);
}

Protecting API Routes

Use ApiJwtMiddleware to protect API routes:

use App\Modules\ForgeAuth\Middlewares\ApiJwtMiddleware;
use Forge\Core\Http\Attributes\ApiRoute;
use Forge\Core\Http\Attributes\Middleware;

#[Middleware('api')]
final class ApiUserController
{
    #[ApiRoute('/users', 'GET')]
    #[Middleware("App\Modules\ForgeAuth\Middlewares\ApiJwtMiddleware")]
    public function index(Request $request): Response
    {
        // This route requires valid JWT token
        // Token is validated and user is loaded automatically
        $user = $this->authService->user();
        
        return $this->apiResponse($user);
    }
}

Custom JWT Claims

You can add custom claims to JWT tokens using callbacks:

use App\Modules\ForgeAuth\Services\ForgeAuthService;

// Add custom claims callback
ForgeAuthService::addCustomClaimsCallback(function ($user, $basePayload) {
    return [
        'role' => $user->role,
        'permissions' => $user->permissions,
        // Add any custom data you need
    ];
});

// Now when tokens are issued, they'll include your custom claims
$tokens = $authService->issueToken($user);

Protected Claims: The following claims are protected and cannot be overridden: user_id, exp, iat, jti, type.

Services

ForgeAuth provides several services for authentication and user management.

ForgeAuthService

The main authentication service providing core authentication methods:

interface ForgeAuthInterface
{
    // Web authentication
    public function register(array $credentials): bool;
    public function login(array $credentials): User;
    public function logout(): void;
    public function user(): ?User;
    
    // JWT methods (available when JWT is enabled)
    public function issueToken(User $user): array;
    public function refreshToken(string $refreshToken): ?array;
    public function resolveUserFromToken(string $token): ?User;
}

Method Details

  • register($credentials) — Register a new user. Throws UserRegistrationException on failure.
  • login($credentials) — Authenticate user and create session. Throws LoginException on failure.
  • logout() — Clear user session.
  • user() — Get current authenticated user from session or JWT token.
  • issueToken($user) — Issue JWT access and refresh tokens. Requires JWT to be enabled.
  • refreshToken($refreshToken) — Refresh access token using refresh token.
  • resolveUserFromToken($token) — Resolve user from JWT token. Used by middleware.

JwtService

Handles JWT encoding and decoding:

class JwtService
{
    public function encode(array $payload): string;
    public function decode(string $token): array;
}
  • Uses HS256 algorithm for signing
  • Validates token signature and expiration
  • Throws JwtTokenInvalidException for invalid tokens
  • Throws JwtTokenExpiredException for expired tokens

UserRepository

Repository for user data access with built-in caching:

interface UserRepositoryInterface
{
    public function create(CreateUserData $data): User;
    public function findById(int $id): ?User;
    public function findByIdentifier(string $identifier): ?User;
    public function findByEmail(string $email): ?User;
}
  • Query results are cached for performance
  • Cache is invalidated on user creation/update
  • Implements UserRepositoryInterface for testability

Middleware

ForgeAuth provides two middleware classes for protecting routes.

AuthMiddleware

Protects web routes using session-based authentication:

use App\Modules\ForgeAuth\Middlewares\AuthMiddleware;

#[Route("/dashboard")]
#[Middleware("App\Modules\ForgeAuth\Middlewares\AuthMiddleware")]
public function dashboard(): Response
{
    // User is authenticated via session
    $user = $this->authService->user();
    return $this->view("dashboard", ["user" => $user]);
}
  • Checks if user is authenticated via session
  • Redirects to /auth/login if not authenticated
  • Returns 401 status code on redirect

ApiJwtMiddleware

Protects API routes using JWT tokens:

use App\Modules\ForgeAuth\Middlewares\ApiJwtMiddleware;

#[ApiRoute("/api/users", "GET")]
#[Middleware("App\Modules\ForgeAuth\Middlewares\ApiJwtMiddleware")]
public function getUsers(): Response
{
    // User is authenticated via JWT token
    $user = $this->authService->user();
    return $this->apiResponse($user);
}
  • Validates Authorization: Bearer <token> header
  • Decodes and validates JWT token
  • Resolves user from token
  • Returns 401 JSON response if token is invalid or missing

Automatic User Resolution: Both middleware classes automatically resolve the authenticated user and make it available via $authService->user().

Models & Data

ForgeAuth provides models and DTOs for user data management.

User Model

The User model represents authenticated users:

#[Table("users")]
#[ProtectedFields(['password'])]
class User extends Model
{
    use HasTimeStamps;
    use CanLoadRelations;

    public int $id;
    public string $status;  // 'active', 'inactive', 'pending'
    public string $identifier;  // Unique username
    public string $email;  // Unique email
    public string $password;  // Hashed password (protected)
    public ?UserMetadataDto $metadata;  // JSON metadata

    #[Relate(RelationKind::HasOne, Profile::class, "user_id")]
    public function profile(): Relation;
}
  • Password field is protected from serialization
  • Supports relationships (e.g., Profile)
  • Includes timestamps (created_at, updated_at)
  • Metadata field supports JSON data

Profile Model

Optional profile model for extended user information:

#[Table("profiles")]
class Profile extends Model
{
    public int $id;
    public int $userId;
    public string $firstName;
    public ?string $lastName;
    public ?string $avatar;
    public ?string $email;
    public ?string $phone;
    // ... other fields
}

DTOs (Data Transfer Objects)

ForgeAuth uses DTOs for type-safe data handling:

  • CreateUserData — For user registration
  • UserDto — For user data transfer
  • ProfileDto — For profile data
  • UserMetadataDto — For user metadata
  • UserNotificationDto — For notification preferences

Validation

ForgeAuth provides validation helpers for login and registration.

ForgeAuthValidate

Static validation methods for authentication forms:

use App\Modules\ForgeAuth\Validation\ForgeAuthValidate;

// Validate login credentials
ForgeAuthValidate::login([
    'identifier' => 'username',
    'password' => 'password123'
]);

// Validate registration data
ForgeAuthValidate::register([
    'identifier' => 'username',
    'email' => 'user@example.com',
    'password' => 'password123'
]);

Validation Rules

Login Validation

  • identifier — Required
  • password — Required

Registration Validation

  • identifier — Required, minimum 3 characters, unique in users table
  • password — Required, minimum 8 characters
// Custom validation messages
ForgeAuthValidate::register($data, [
    'required' => 'The :field field is required!',
    'min' => 'The :field field must be at least :value characters.',
    'unique' => 'The :field is already taken.'
]);

Controllers

ForgeAuth includes ready-to-use controllers for authentication and user management.

WebLoginController

Handles web login and logout routes:

  • GET /auth/login — Show login form
  • POST /auth/login — Process login
  • POST /auth/logout — Logout user

ApiLoginController

Handles API login and token refresh:

  • POST /api/auth/login — Login and get JWT tokens
  • POST /api/auth/refresh — Refresh access token

WebUserController

Web routes for user management:

  • GET /users — List users (with pagination)
  • GET /users/{id} — Get user by ID
  • GET /users/export — Export users to CSV

ApiUserController

API routes for user management:

  • GET /api/users — List users (with pagination)
  • GET /api/users/{id} — Get user by ID
  • GET /api/users/export — Export users to CSV

Customization: You can extend or replace these controllers with your own implementations. They're provided as examples and starting points.

Database Migrations

ForgeAuth includes database migrations that run automatically after installation.

Users Table

The users table stores user accounts:

// Migration: CreateUsersTable
#[Table(name: "users")]
#[Timestamps]
#[SoftDelete]
#[MetaData]
class CreateUsersTable extends Migration
{
    public int $id;  // Primary key
    public string $status;  // ENUM: 'active', 'inactive', 'pending'
    public string $identifier;  // Unique username
    public string $email;  // Unique email
    public string $password;  // Hashed password
}
  • Includes created_at and updated_at timestamps
  • Supports soft deletes (deleted_at)
  • Includes metadata column for JSON data
  • Indexes on id, email, and deleted_at

Profiles Table

The profiles table stores extended user information:

// Migration: CreateProfilesTable
#[Table(name: "profiles")]
#[Timestamps]
#[SoftDelete]
#[MetaData]
class CreateProfilesTable extends Migration
{
    public int $id;
    public int $userId;  // Foreign key to users
    public string $firstName;
    public ?string $lastName;
    public ?string $avatar;
    public ?string $email;
    public ?string $phone;
    // ... other fields
}

Tenant Support

ForgeAuth includes tenant-specific migrations for multi-tenant applications:

  • Tenants/CreateTenantUsersTable.php — Tenant-specific users table
  • Works with ForgeMultiTenant module

Usage Examples

Complete examples of using ForgeAuth in your controllers.

User Registration

use App\Modules\ForgeAuth\Services\ForgeAuthService;
use App\Modules\ForgeAuth\Validation\ForgeAuthValidate;
use Forge\Core\Helpers\Flash;
use Forge\Core\Helpers\Redirect;
use Forge\Exceptions\ValidationException;

#[Route("/", "POST")]
public function register(Request $request): Response
{
    try {
        // Validate input
        ForgeAuthValidate::register($request->postData);
        
        // Sanitize input
        $credentials = $this->sanitize($request->postData);
        
        // Register user
        $this->forgeAuthService->register($credentials);
        
        Flash::set("success", "User registered successfully");
        return Redirect::to("/");
    } catch (ValidationException) {
        return Redirect::to("/");
    }
}

Protected Route

use App\Modules\ForgeAuth\Services\ForgeAuthService;
use App\Modules\ForgeAuth\Middlewares\AuthMiddleware;
use Forge\Core\Http\Attributes\Middleware;
use Forge\Core\Routing\Route;

#[Service]
#[Middleware("web")]
final class DashboardController
{
    public function __construct(
        private readonly ForgeAuthService $authService
    ) {}

    #[Route("/dashboard")]
    #[Middleware("App\Modules\ForgeAuth\Middlewares\AuthMiddleware")]
    public function welcome(): Response
    {
        $data = [
            "title" => "Welcome to Dashboard",
            "user" => $this->authService->user() ?? [],
        ];

        return $this->view(view: "pages/dashboard/index", data: $data);
    }
}

API Authentication with JWT

use App\Modules\ForgeAuth\Services\ForgeAuthService;
use App\Modules\ForgeAuth\Middlewares\ApiJwtMiddleware;
use Forge\Core\Http\Attributes\ApiRoute;
use Forge\Core\Http\Attributes\Middleware;

#[Middleware('api')]
final class ApiUserController
{
    public function __construct(
        private readonly ForgeAuthService $authService
    ) {}

    #[ApiRoute('/api/users/me', 'GET')]
    #[Middleware("App\Modules\ForgeAuth\Middlewares\ApiJwtMiddleware")]
    public function getCurrentUser(): Response
    {
        // User is automatically loaded from JWT token
        $user = $this->authService->user();
        
        return $this->apiResponse([
            'user' => $user,
        ]);
    }
}

Using JWT Tokens in Mobile Apps

Example of how mobile apps would use JWT tokens:

// Login and get tokens
const response = await fetch('/api/auth/login', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
        identifier: 'username',
        password: 'password123'
    })
});

const { user, tokens } = await response.json();

// Store tokens securely
localStorage.setItem('access_token', tokens.access_token);
localStorage.setItem('refresh_token', tokens.refresh_token);

// Use access token for API requests
const apiResponse = await fetch('/api/users/me', {
    headers: {
        'Authorization': `Bearer ${tokens.access_token}`
    }
});

// Refresh token when access token expires
const refreshResponse = await fetch('/api/auth/refresh', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
        refresh_token: tokens.refresh_token
    })
});

const newTokens = await refreshResponse.json();

Mobile Support

ForgeAuth provides opt-in JWT support for mobile applications. JWT is not enabled by default — you enable it when you need it.

Why Opt-In JWT?

JWT support is opt-in because:

  • Most web applications don't need JWT — sessions work perfectly
  • JWT adds complexity (secret management, token refresh, etc.)
  • You should only enable what you need
  • Clear separation between web and mobile authentication

Enabling JWT for Mobile

To enable JWT support for mobile applications:

  1. Set security.jwt.enabled = true in configuration
  2. Set a strong security.jwt.secret key
  3. Configure token TTL values if needed
  4. Use ApiLoginController for login endpoints
  5. Use ApiJwtMiddleware to protect API routes

Mobile Authentication Flow

Mobile apps authenticate using this flow:

  1. User enters credentials in mobile app
  2. App sends credentials to POST /api/auth/login
  3. Server validates credentials and issues JWT tokens
  4. App stores tokens securely (keychain, secure storage, etc.)
  5. App includes access token in Authorization: Bearer <token> header for API requests
  6. When access token expires, app uses refresh token to get new tokens

Token Refresh Flow

Access tokens are short-lived (default: 15 minutes). Use refresh tokens to get new access tokens:

// When access token expires (401 response)
async function refreshAccessToken() {
    const refreshToken = localStorage.getItem('refresh_token');
    
    const response = await fetch('/api/auth/refresh', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ refresh_token: refreshToken })
    });
    
    if (response.ok) {
        const tokens = await response.json();
        localStorage.setItem('access_token', tokens.access_token);
        localStorage.setItem('refresh_token', tokens.refresh_token);
        return tokens.access_token;
    } else {
        // Refresh token expired, user must login again
        redirectToLogin();
    }
}

Custom Claims for Mobile

Add custom claims to JWT tokens for mobile-specific data:

use App\Modules\ForgeAuth\Services\ForgeAuthService;

// Add custom claims callback
ForgeAuthService::addCustomClaimsCallback(function ($user, $basePayload) {
    return [
        'role' => $user->role,
        'permissions' => $user->permissions,
        'subscription_tier' => $user->subscriptionTier,
        // Any data your mobile app needs
    ];
});

Mobile-First Design: JWT tokens are designed for stateless authentication, perfect for mobile apps that need to work offline or with intermittent connectivity.

Best Practices

Recommendations for using ForgeAuth effectively and securely.

Things That Often Help

  • • Use web sessions for traditional web applications
  • • Only enable JWT when you need mobile/API support
  • • Use strong, random JWT secrets (minimum 32 characters)
  • • Store JWT secrets in environment variables, never in code
  • • Use HTTPS in production for all authentication endpoints
  • • Implement proper error handling for authentication failures
  • • Use the provided middleware instead of manual checks
  • • Leverage login throttling to prevent brute-force attacks

Things to Consider

  • • Don't enable JWT if you only need web authentication
  • • Don't store JWT secrets in version control
  • • Don't use weak passwords or skip validation
  • • Don't expose sensitive user data in JWT tokens
  • • Don't ignore login throttling warnings
  • • Don't use HTTP for authentication in production
  • • Don't store passwords in plain text (bcrypt is automatic)
  • • Don't skip session regeneration on login

Security Considerations

  • Password Hashing: ForgeAuth automatically hashes passwords with bcrypt. Never store plain text passwords.
  • Session Security: Sessions are automatically regenerated on login to prevent session fixation attacks.
  • JWT Secrets: Use strong, random secrets. Rotate secrets periodically in production.
  • Token Expiration: Access tokens are short-lived (15 minutes). Use refresh tokens for long-term authentication.
  • HTTPS: Always use HTTPS in production. Never send credentials or tokens over HTTP.
  • Login Throttling: Built-in throttling prevents brute-force attacks. Adjust limits based on your needs.

When to Use Web vs API Authentication

Use Web Sessions When:

  • • Building traditional web applications
  • • Users interact via browser
  • • You want automatic session management
  • • You don't need stateless authentication

Use JWT When:

  • • Building mobile applications
  • • Building API services
  • • You need stateless authentication
  • • You need cross-domain authentication