Skip to main content

Overview

JWT (JSON Web Token) authentication is used for dashboard users to manage agents, services, and approval workflows. GaiterGuard uses a dual-token system:
  • Access Token: Short-lived (15 minutes) for API requests
  • Refresh Token: Long-lived (7 days) for obtaining new access tokens

Token Configuration

From /home/daytona/workspace/source/backend/src/config/env.ts:26-27:
  • JWT_ACCESS_EXPIRY: 15m (15 minutes)
  • JWT_REFRESH_EXPIRY: 7d (7 days)

Authentication Endpoints

Register User

Create a new dashboard user account.

Request Body

string
required
Valid email address. Must match format: /^[^\s@]+@[^\s@]+\.[^\s@]+$/
string
required
Password with minimum 8 characters. Hashed using Argon2id (memory cost: 65536, time cost: 2).

Response Fields

object
The created user record (password hash excluded)
number
Unique user identifier
string
User’s email address

Error Responses

Email Already Exists (409 Conflict)
Validation Error (400 Bad Request)

Login

Authenticate with email and password to receive access and refresh tokens.

Request Body

string
required
User’s registered email address
string
required
User’s password

Response Fields

string
JWT access token valid for 15 minutes. Use in Authorization: Bearer {token} header.
string
JWT refresh token valid for 7 days. Use to obtain new access tokens. Stored as hashed value in database.
object
Authenticated user information

Error Responses

Invalid Credentials (401 Unauthorized)
Returned when:
  • Email doesn’t exist in database
  • Password verification fails

Refresh Access Token

Exchange a valid refresh token for a new access + refresh token pair. Implements token rotation - the old refresh token is invalidated.

Request Body

string
required
Valid refresh token from login or previous refresh

Response Fields

string
New JWT access token valid for 15 minutes
string
New JWT refresh token valid for 7 days. The old refresh token is deleted from database.

Token Rotation Flow

From /home/daytona/workspace/source/backend/src/services/auth.service.ts:135-196:
  1. Verify refresh token JWT signature
  2. Extract user ID from token
  3. Query refresh_tokens table for matching hash
  4. Delete old refresh token (rotation)
  5. Generate new access + refresh token pair
  6. Store new refresh token hash in database
  7. Return new tokens

Error Responses

Invalid Refresh Token (401 Unauthorized)
Returned when:
  • Token signature verification fails
  • Token is expired
  • Token hash not found in database
  • Token already used (due to rotation)

Get Current User

Retrieve authenticated user information.

Headers

string
required
Bearer token format: Bearer YOUR_ACCESS_TOKEN

Response Fields

object
Current user information
number
User ID
string
User email
string
ISO 8601 timestamp of account creation

Using JWT Tokens

Making Authenticated Requests

Include the access token in the Authorization header:

Access Token Expiry Handling

Implement automatic token refresh when access token expires:

JWT Token Structure

Access Token

Generated by /home/daytona/workspace/source/backend/src/utils/jwt.ts:36-44:
Decoded Payload
  • Algorithm: HS256 (HMAC-SHA256)
  • No type claim (distinguishes from refresh tokens)

Refresh Token

Generated by /home/daytona/workspace/source/backend/src/utils/jwt.ts:51-62:
Decoded Payload
  • Algorithm: HS256
  • Includes type: "refresh" claim for validation

Authentication Middleware

The requireAuth middleware (from backend/src/middleware/auth.ts:29) protects dashboard routes:
  1. Extract Authorization header
  2. Validate Bearer prefix format
  3. Extract token after prefix
  4. Verify token signature and expiry using jose library
  5. Extract user ID from sub claim
  6. Return { userId } for route handlers

Protected Routes

All agent management endpoints require JWT authentication:
  • POST /agents - Create agent
  • GET /agents - List agents
  • GET /agents/:id - Get agent details
  • PUT /agents/:id - Update agent
  • DELETE /agents/:id - Delete agent
  • PUT /agents/:id/services - Update agent services

Error Responses

Missing Authorization Header

Invalid Header Format

The header must start with Bearer (note the space).

Invalid or Expired Token

Returned when:
  • Token signature verification fails
  • Token is expired
  • Token is malformed

Security Features

Passwords are hashed using Argon2id with strong parameters:
  • Memory cost: 65536 KB
  • Time cost: 2 iterations
  • Built-in salt generation
Implementation: backend/src/services/auth.service.ts:54-58
Refresh tokens are single-use. Each refresh operation:
  • Deletes the old refresh token from database
  • Issues a new refresh token
  • Prevents token replay attacks
Implementation: backend/src/services/auth.service.ts:176
  • Refresh tokens stored as hashed values in database
  • Access tokens are stateless (not stored)
  • Tokens use HS256 algorithm with secret key
15-minute access token expiry minimizes exposure window if token is compromised. Use refresh tokens to obtain new access tokens.

Best Practices

Store Tokens Securely

  • Use secure HTTP-only cookies for web apps
  • Store in encrypted storage on mobile
  • Never expose tokens in URLs or logs

Handle Token Expiry Gracefully

  • Implement automatic refresh on 401 errors
  • Pre-emptively refresh before expiry
  • Clear tokens on logout

Use HTTPS

Always transmit tokens over HTTPS to prevent interception

Implementation Reference

Source code locations:
  • Auth routes: backend/src/routes/auth.ts
  • Auth service: backend/src/services/auth.service.ts
  • JWT utilities: backend/src/utils/jwt.ts
  • Auth middleware: backend/src/middleware/auth.ts:29
  • Config: backend/src/config/env.ts