DeployStack Docs

Backend Authentication System

This document provides technical details about the DeployStack backend authentication system implementation. For user-facing authentication configuration, see Authentication Methods. For OAuth provider implementation details, see OAuth Provider Implementation and OAuth2 Server Implementation.

Architecture Overview

The backend authentication system is built on several key components:

  • Lucia v3 - Core session management and authentication library
  • Argon2 - Industry-standard password hashing
  • Arctic - OAuth 2.0 client library for provider integration
  • Database-backed sessions - SQLite/Turso storage for session persistence
  • Dual authentication - Support for both cookie sessions and OAuth2 Bearer tokens

Authentication Flow Types

The backend supports multiple authentication flows to accommodate different client types and use cases:

1. Email/Password Authentication

Traditional username/password authentication with email verification:

  • Registration (/api/auth/email/register) - Creates new user accounts
  • Login (/api/auth/email/login) - Authenticates existing users
  • Email Verification - Optional verification requirement based on global settings
  • Password Reset - Secure token-based password recovery

2. OAuth Provider Authentication

Third-party authentication via OAuth providers (currently GitHub):

  • Provider Login (/api/auth/github/login) - Initiates OAuth flow
  • OAuth Callback (/api/auth/github/callback) - Handles provider response
  • Account Linking - Automatically links OAuth accounts to existing users by email
  • User Provisioning - Creates new users from OAuth profile data

3. OAuth2 Server Authentication

Bearer token authentication for programmatic API access:

  • Authorization (/api/oauth2/auth) - OAuth2 authorization endpoint
  • Token Exchange (/api/oauth2/token) - Exchanges codes for access tokens
  • Bearer Authentication - API access using Authorization header
  • Scope-based Permissions - Fine-grained access control

Core Components

Session Management

Sessions are managed through Lucia v3 with database persistence:

Session Storage

Sessions are stored in the authSession table with the following structure:

  • Session ID: 40-character cryptographically random identifier
  • User ID: Foreign key reference to the authenticated user
  • Expiration: 30-day lifetime from creation
  • Cookie Attributes: httpOnly, secure (production), sameSite (lax)

Session Lifecycle

  1. Creation: Generated after successful authentication
  2. Validation: Checked on each request via authHook
  3. Refresh: Sessions are not automatically extended
  4. Expiration: Expired sessions are deleted on validation attempt
  5. Logout: Explicit session deletion

Password Security

Passwords are secured using Argon2id with carefully chosen parameters:

Hashing Parameters

  • Algorithm: Argon2id (resistant to side-channel and GPU attacks)
  • Memory Cost: 19456 KB (19 MB)
  • Time Cost: 2 iterations
  • Parallelism: 1 thread
  • Output Length: 32 bytes
  • Salt: Unique per password, automatically generated

Password Verification

The verification process uses constant-time comparison to prevent timing attacks:

  1. Extract stored hash and salt from database
  2. Re-compute hash with provided password
  3. Compare hashes using constant-time algorithm
  4. Return authentication result

Authentication Hooks

The backend uses Fastify hooks for request-level authentication:

authHook (Global)

Runs on every request to establish authentication context:

  • Reads session cookie if present
  • Validates session against database
  • Populates request.user and request.session
  • Handles expired session cleanup
  • Skips authentication if database not ready

requireAuthHook (Route-specific)

Enforces authentication on protected routes:

  • Checks for valid user and session
  • Returns 401 Unauthorized if not authenticated
  • Used as preValidation hook on protected endpoints

User Registration Flow

Email Registration Process

  1. Validation: Input validation using Zod schemas
  2. Uniqueness Check: Verify username and email availability
  3. Password Hashing: Secure hash generation with Argon2
  4. User Creation: Database insertion with role assignment
  5. First User Logic: Automatic global_admin role for first user
  6. Email Verification: Send verification email (if enabled)
  7. Team Creation: Automatic default team creation
  8. Session Creation: Immediate login after registration
  9. Response: User data and success message

Role Assignment

  • First User: Automatically assigned global_admin role
  • Subsequent Users: Assigned global_user role
  • OAuth Users: Always assigned global_user role
  • Email Verification: First user auto-verified, others depend on settings

Login Authentication Flow

Email Login Process

  1. Global Check: Verify login is enabled in settings
  2. User Lookup: Find user by email or username
  3. Password Verification: Argon2 hash comparison
  4. Email Verification Check: Ensure email is verified (if required)
  5. Session Creation: Generate new 30-day session
  6. Cookie Setting: Set httpOnly session cookie
  7. Response: User data and session established

Authentication State

After successful login, the following state is established:

  • Session Cookie: Contains session ID
  • Database Session: Active session record
  • User Context: Available in request.user
  • Session Context: Available in request.session

Email Verification System

Verification Requirements

  • Controlled by: global.send_mail setting
  • First User: Always auto-verified for system access
  • Email Users: Must verify before login (when enabled)
  • OAuth Users: Auto-verified (provider emails trusted)

Verification Token Flow

  1. Token Generation: 32-character random token
  2. Token Storage: Hashed with Argon2 (same as passwords)
  3. Email Dispatch: Verification link sent via SMTP
  4. Token Validation: Constant-time comparison
  5. Account Activation: Email marked as verified
  6. Token Cleanup: Single-use, expires after 24 hours

Password Reset Flow

Reset Process

  1. Request Initiation: User provides email address
  2. Token Generation: Secure random reset token
  3. Token Storage: Hashed and stored with expiration
  4. Email Notification: Reset link sent to user
  5. Token Validation: Verify token and expiration
  6. Password Update: New password hashed and stored
  7. Token Invalidation: Used tokens are deleted
  8. Session Creation: Optional auto-login after reset

Security Measures

  • Rate Limiting: Prevent brute force attempts
  • Token Expiration: 1-hour validity window
  • Single Use: Tokens invalidated after use
  • User Notification: Email sent on password change

Dual Authentication Support

The backend supports both cookie-based and Bearer token authentication simultaneously:

  • Primary Use: Web application sessions
  • Validation: Via authHook on every request
  • Storage: Server-side session with cookie identifier
  • Lifetime: 30-day expiration

Bearer Token Authentication

  • Primary Use: CLI and API access
  • Validation: Via oauthMiddleware
  • Format: OAuth2 access tokens
  • Lifetime: 1-hour access, 30-day refresh

Middleware Integration

Endpoints can accept either authentication method using requireAuthenticationAny():

  • First checks for cookie session
  • Falls back to Bearer token validation
  • Populates same request.user interface
  • Maintains authentication type in context

Security Best Practices

Implementation Security

  1. Password Storage: Never store plaintext, always use Argon2
  2. Session Management: Cryptographically secure IDs, proper expiration
  3. Token Security: Constant-time comparisons, secure random generation
  4. HTTPS Enforcement: Secure cookies in production
  5. CSRF Protection: State parameters in OAuth, sameSite cookies

Validation and Sanitization

  • Input Validation: All inputs validated with Zod schemas
  • Email Normalization: Lowercase conversion before storage
  • SQL Injection Prevention: Parameterized queries via Drizzle ORM
  • XSS Prevention: httpOnly cookies, no client-side session access

Database Schema

The authentication system uses the following core tables:

authUser Table

Stores user account information:

  • User identification (id, username, email)
  • Authentication data (hashed_password, auth_type)
  • Profile information (first_name, last_name)
  • OAuth provider IDs (github_id)
  • Account status (email_verified, role_id)

authSession Table

Manages active user sessions:

  • Session identification (id)
  • User association (user_id)
  • Expiration tracking (expires_at)

Additional Tables

Supporting tables for full functionality:

  • email_verification_tokens: Email verification tokens
  • password_reset_tokens: Password reset tokens
  • oauth_authorization_codes: OAuth2 authorization codes
  • oauth_access_tokens: OAuth2 access tokens
  • oauth_refresh_tokens: OAuth2 refresh tokens

API Reference

For a complete list of authentication API endpoints and their specifications, see the Backend API Documentation. The API documentation includes OpenAPI specifications with detailed request/response schemas for all authentication endpoints.