---
title: Authentication Architecture
description: JWT-based authentication with OAuth providers and session management
---

## Overview

InsForge implements a modern, secure authentication system using JWT tokens with RSA signing, OAuth provider integration, and database-backed session management.

## Technology Stack

```mermaid
graph TB
    Client[Client Application] --> SDK[InsForge SDK]
    SDK --> AuthAPI[Auth API]
    
    AuthAPI --> JWT[JWT Service]
    AuthAPI --> OAuth[OAuth Providers]
    AuthAPI --> DB[(PostgreSQL)]
    
    OAuth --> Google[Google OAuth 2.0]
    OAuth --> GitHub[GitHub OAuth]
    
    JWT --> Secret[Shared Secret]
    JWT --> Validation[Token Validation]
    
    DB --> Users[auth.users Table]
    DB --> Providers[auth.user_providers]
    
    style Client fill:#1e293b,stroke:#475569,color:#e2e8f0
    style SDK fill:#1e40af,stroke:#3b82f6,color:#dbeafe
    style AuthAPI fill:#166534,stroke:#22c55e,color:#dcfce7
    style JWT fill:#c2410c,stroke:#fb923c,color:#fed7aa
    style OAuth fill:#6b21a8,stroke:#a855f7,color:#f3e8ff
    style DB fill:#0e7490,stroke:#06b6d4,color:#cffafe
    style Secret fill:#991b1b,stroke:#ef4444,color:#fee2e2
    style Google fill:#4c1d95,stroke:#8b5cf6,color:#ede9fe
    style GitHub fill:#1e293b,stroke:#64748b,color:#f1f5f9
    style Validation fill:#991b1b,stroke:#ef4444,color:#fee2e2
    style Users fill:#0e7490,stroke:#22d3ee,color:#cffafe
    style Providers fill:#0e7490,stroke:#22d3ee,color:#cffafe
```

## Core Components

| Component | Technology | Purpose |
|-----------|------------|---------|
| **Token Format** | JWT with HS256 | Stateless authentication tokens |
| **Signing Algorithm** | HMAC-SHA256 | Symmetric key signing with shared secret |
| **Authentication** | Stateless JWT | No server-side session storage |
| **Password Hashing** | bcryptjs (10 rounds) | Secure password storage |
| **OAuth Providers** | Google, GitHub, Microsoft, Discord, and more | Social authentication |
| **Token Expiry** | Fixed | 7 days for user tokens, never for anon tokens |

## Authentication Flow

### Password-Based Authentication

```mermaid
sequenceDiagram
    participant Client
    participant SDK
    participant API
    participant DB
    participant JWT
    
    Client->>SDK: signUp/signIn(email, password)
    SDK->>API: POST /api/auth/users or /sessions
    API->>DB: Verify credentials
    DB-->>API: User data
    API->>JWT: Generate token (HS256)
    JWT-->>API: Signed JWT
    API-->>SDK: {user, accessToken}
    SDK-->>Client: Authenticated
```

### Email Verification And Password Reset Link Flows

InsForge supports both `code` and `link` methods for email verification and password reset.

- `code` method: user receives a 6-digit code and submits it through the app.
- `link` method: user clicks an email link that always opens an InsForge backend endpoint first.
- `redirectTo` must be included in `allowedRedirectUrls` before link-based flows can use it.
- If `allowedRedirectUrls` is empty, InsForge allows all redirects for smoother development UX. Do not rely on that behavior in production.

<Note>
Verification and password-reset emails are sent through InsForge Cloud by default. To send them from your own server with custom subject lines and HTML, configure [Custom SMTP](/core-concepts/email/custom-smtp) under **Authentication → Email** in the dashboard — the four `email-verification-*` and `reset-password-*` templates are fully editable.
</Note>

For link-based email verification:

- The email link opens `GET /api/auth/email/verify-link?token=...`
- InsForge verifies the token on the backend
- InsForge redirects the browser to the stored `redirectTo`
- Query params:
  - `insforge_status`: `success` or `error`
  - `insforge_type`: always `verify_email`
  - `insforge_error`: present only on error
- Recommended: use your sign-in page as `redirectTo`, then show a success message and ask the user to sign in with their email and password

For link-based password reset:

- The email link opens `GET /api/auth/email/reset-password-link?token=...`
- InsForge validates the token on the backend
- InsForge redirects the browser to the stored `redirectTo`
- Query params:
  - `token`: present only when reset is ready
  - `insforge_status`: `ready` or `error`
  - `insforge_type`: always `reset_password`
  - `insforge_error`: present only on error
- Your app should render the reset form only when `insforge_status=ready` and `token` is present

### Disabling New User Signups

When a project is in closed-beta, at capacity, or under a bot wave, you can block all new account creation without taking auth down.

**Dashboard:** Auth Settings → General → **Disable New User Signups** toggle.

**API (admin only):**
```http
PUT /api/auth/config
Authorization: Bearer <admin-jwt>
Content-Type: application/json

{ "disableSignup": true }
```

Behavior when the toggle is **on**:

| Scenario | Result |
|----------|--------|
| `POST /api/auth/users` without admin token | `403 AUTH_SIGNUP_DISABLED` |
| First-time OAuth login (unknown account) | `403 AUTH_SIGNUP_DISABLED` |
| Existing user signs in (email or OAuth) | Allowed — unaffected |
| Admin creates user via dashboard or API | Allowed — bypass is automatic when bearer token carries `role: project_admin` |

### Session Recovery

InsForge uses short-lived access tokens plus refresh tokens.

- Web clients store the refresh token in an httpOnly cookie
- For browser apps, call `auth.getCurrentUser()` during startup. The SDK will use the httpOnly refresh cookie automatically when it can refresh the session
- Server, mobile, and other non-browser clients do not get that automatic cookie-based refresh and should call the refresh endpoint explicitly

### OAuth Flow

```mermaid
sequenceDiagram
    participant Client
    participant SDK
    participant API
    participant Provider
    participant DB
    
    Client->>SDK: signInWithOAuth(provider)
    SDK->>API: GET /api/auth/oauth/{provider}
    API-->>Client: Redirect to provider
    Client->>Provider: Authorize
    Provider-->>Client: Callback with code
    Client->>API: GET /callback?code=xxx
    API->>Provider: Exchange code for token
    Provider-->>API: User info
    API->>DB: Create/update user
    API->>DB: Link OAuth account
    API-->>Client: {user, accessToken}
```

## JWT Token Structure

### Token Payload

```json
{
  "sub": "user_id_uuid",
  "email": "user@example.com",
  "role": "authenticated",
  "iat": 1704067200,
  "exp": 1704672000,
  "iss": "insforge",
  "aud": "insforge-api"
}
```

### Token Claims

| Claim | Description | Example |
|-------|-------------|---------|
| `sub` | Subject (User ID) | UUID format |
| `email` | User's email | user@example.com |
| `role` | User role/permissions | authenticated, admin |
| `iat` | Issued at timestamp | Unix timestamp |
| `exp` | Expiration timestamp | Unix timestamp |
| `iss` | Token issuer | insforge |
| `aud` | Intended audience | insforge-api |

## Security Features

<CardGroup cols={2}>
  <Card title="HS256 Signing" icon="signature">
    Tokens signed with HMAC-SHA256 using shared secret key
  </Card>
  
  <Card title="bcrypt Hashing" icon="lock">
    Passwords hashed with bcryptjs using 10 salt rounds
  </Card>
  
  <Card title="OAuth State" icon="shield-check">
    CSRF protection via state parameter in OAuth flows
  </Card>
  
  <Card title="Stateless Auth" icon="clock">
    JWT tokens with built-in expiry, no server-side sessions
  </Card>
  
  <Card title="Token Rotation" icon="arrows-rotate">
    Support for refresh token rotation (coming soon)
  </Card>
  
  <Card title="Rate Limiting" icon="gauge">
    Protection against brute force attacks
  </Card>

  <Card title="Signup Toggle" icon="toggle-on">
    Disable new user signups instantly while existing users keep signing in
  </Card>
</CardGroup>

## API Endpoints

### Authentication Endpoints

| Method | Endpoint | Purpose |
|--------|----------|---------|
| POST | `/api/auth/users` | Register new user |
| POST | `/api/auth/sessions` | Login with email/password |
| GET | `/api/auth/sessions/current` | Get current user (requires auth) |
| POST | `/api/auth/email/send-verification` | Send verification code or link |
| POST | `/api/auth/email/verify` | Verify email with 6-digit code |
| POST | `/api/auth/email/send-reset-password` | Send password reset code or link |
| POST | `/api/auth/email/exchange-reset-password-token` | Exchange reset code for reset token |
| POST | `/api/auth/email/reset-password` | Reset password with token |
| POST | `/api/auth/admin/sessions` | Admin login (local development) |
| POST | `/api/auth/admin/sessions/exchange` | Exchange authorization code (cloud platform) |
| POST | `/api/auth/admin/refresh` | Refresh dashboard admin session |
| POST | `/api/auth/admin/logout` | Logout dashboard admin session |

### OAuth Endpoints

| Method | Endpoint | Purpose |
|--------|----------|---------|
| GET | `/api/auth/oauth/:provider` | Initiate OAuth flow for built-in providers |
| GET | `/api/auth/oauth/:provider/callback` | Built-in OAuth callback handler |
| GET | `/api/auth/oauth/custom/:key` | Initiate OAuth flow for custom providers |
| GET | `/api/auth/oauth/custom/:key/callback` | Custom OAuth callback handler |

### Admin Endpoints

| Method | Endpoint | Purpose |
|--------|----------|---------|
| GET | `/api/auth/users` | List all users (admin only) |
| DELETE | `/api/auth/users` | Delete users (admin only) |

## OAuth Provider Configuration

InsForge supports multiple OAuth providers including Google, GitHub, Microsoft, Discord, LinkedIn, Facebook and more coming soon.

### Custom OAuth Providers

Admins can add custom OIDC-compatible OAuth providers from the dashboard at `Auth Methods` without writing backend code.

Required for custom provider setup:

- `name` (display label)
- `key` (unique lowercase key, e.g. `okta-company`)
- `discovery endpoint` (`.well-known/openid-configuration` URL)
- `client ID`
- `client secret` (stored through the existing secret-management flow)

PKCE is always enabled for custom provider flows. Custom providers are stored in `auth.custom_oauth_configs` and handled by dedicated routes under `/api/auth/oauth/custom/*`, keeping built-in provider behavior isolated. Users authenticated through custom providers are linked into the same `auth.users` and `auth.user_providers` model.

### Example: Google OAuth 2.0

- **Authorization URL**: `https://accounts.google.com/o/oauth2/v2/auth`
- **Token URL**: `https://oauth2.googleapis.com/token`
- **Scopes**: `openid`, `email`, `profile`
- **Required**: Client ID, Client Secret, Redirect URI

### Example: GitHub OAuth

- **Authorization URL**: `https://github.com/login/oauth/authorize`
- **Token URL**: `https://github.com/login/oauth/access_token`
- **Scopes**: `read:user`, `user:email`
- **Required**: Client ID, Client Secret, Redirect URI

## Token Validation

### Validation Steps

1. **Format Check**: Verify JWT structure (header.payload.signature)
2. **Signature Verification**: Validate with RSA public key
3. **Expiry Check**: Ensure token hasn't expired
4. **Issuer/Audience**: Verify iss and aud claims
5. **User Lookup**: Check user exists in auth.users table
6. **User Status**: Ensure user account is active

### Middleware Flow

```javascript
// Simplified validation flow (stateless)
async function validateToken(token) {
  // 1. Decode and verify JWT
  const decoded = jwt.verify(token, publicKey, {
    algorithms: ['RS256'],
    issuer: 'insforge',
    audience: 'insforge-api'
  });
  
  // 2. Check user exists (optional)
  const user = await db.query(
    'SELECT * FROM auth.users WHERE id = $1',
    [decoded.sub]
  );
  
  // 3. Return user context from JWT
  return {
    userId: decoded.sub,
    email: decoded.email,
    role: decoded.role
  };
}
```

## Security Best Practices

<CardGroup cols={2}>
  <Card title="HTTPS Only" icon="lock">
    Always use HTTPS in production to protect tokens in transit
  </Card>
  
  <Card title="Secure Storage" icon="database">
    Store tokens in httpOnly cookies or secure storage
  </Card>
  
  <Card title="Short Expiry" icon="clock">
    Use short-lived access tokens with refresh tokens
  </Card>
  
  <Card title="Revocation" icon="ban">
    Implement token revocation for compromised accounts
  </Card>
  
  <Card title="Password Policy" icon="key">
    Enforce strong password requirements
  </Card>
  
  <Card title="2FA Support" icon="mobile">
    Two-factor authentication (coming soon)
  </Card>
</CardGroup>

## Environment Variables

| Variable | Description | Example |
|----------|-------------|---------|
| `JWT_SECRET` | RSA private key or secret | Base64 encoded key |
| `GOOGLE_CLIENT_ID` | Google OAuth client ID | xxx.apps.googleusercontent.com |
| `GOOGLE_CLIENT_SECRET` | Google OAuth secret | Secret string |
| `GITHUB_CLIENT_ID` | GitHub OAuth client ID | GitHub app ID |
| `GITHUB_CLIENT_SECRET` | GitHub OAuth secret | Secret string |
| `TOKEN_EXPIRY` | Token lifetime | 7d, 24h, 3600 |

## SDK References

Choose the authentication SDK guide for your platform:

<CardGroup cols={2}>
  <Card title="TypeScript" icon="js" href="/sdks/typescript/auth">
    Web and Node.js applications with full OAuth and session management
  </Card>

  <Card title="Swift" icon="swift" href="/sdks/swift/auth">
    iOS, macOS, tvOS, and watchOS with Sign in with Apple support
  </Card>

  <Card title="Kotlin" icon="android" href="/sdks/kotlin/auth">
    Android applications with Google Sign-In integration
  </Card>
</CardGroup>
