> ## Documentation Index
> Fetch the complete documentation index at: https://docs.switchbord.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Authentication & Access Control

> Session management, RBAC, API key lifecycle, password policy, and MFA for Switchbord workspaces.

## Supabase Auth Integration

Switchbord uses Supabase Auth as its authentication backbone. All user sessions are managed through Supabase's JWT-based session system, with server-side validation on every API request.

<Note>
  Authentication is enforced at the API route level. Every route begins with session validation before any business logic executes.
</Note>

## Session Management

### Session Timeboxing

Sessions are subject to two independent expiry controls:

| Control            | Value   | Description                                     |
| ------------------ | ------- | ----------------------------------------------- |
| Absolute timeout   | 8 hours | Session expires after 8h regardless of activity |
| Inactivity timeout | 1 hour  | Session expires if no activity for 1h           |

These limits are configured in Supabase and enforced server-side — extending them requires an admin configuration change, not a client workaround.

### Session Revocation on Member Removal

When a workspace member is removed, their active sessions are immediately invalidated across all devices:

```typescript theme={null}
// Called during workspace member removal
await supabaseAdmin.auth.admin.signOut(userId, 'global');
```

The `'global'` scope ensures that all sessions for the user are terminated — not just the current one. This prevents a removed member from continuing to use an existing session after losing workspace access.

## Password Policy

Switchbord enforces the following password requirements, configured in Supabase:

* Minimum **12 characters**
* At least one **uppercase letter**
* At least one **digit**
* Enforced at signup and password change

<Tip>
  Users are encouraged to use a password manager and generate unique passwords for each service.
</Tip>

## Multi-Factor Authentication

Supabase TOTP (Time-based One-Time Password) MFA is available for all users. Users can enroll an authenticator app from their account settings.

<Warning>
  MFA **enforcement** (requiring MFA for all workspace members) is currently **planned** and tracked in the roadmap. Until enforcement is implemented, MFA is opt-in per user. Organizations with strict compliance requirements should instruct their members to enroll.
</Warning>

## Role-Based Access Control

Switchbord implements four roles with distinct permission levels. Role assignment is managed by workspace owners and admins.

### Role Hierarchy

| Role          | Description                                                            |
| ------------- | ---------------------------------------------------------------------- |
| **owner**     | Full workspace control including billing, deletion, and owner transfer |
| **admin**     | Full operational control including member management and all settings  |
| **developer** | API access, integration configuration, technical settings              |
| **operator**  | Day-to-day operations: conversations, contacts, sending messages       |

### Role Enforcement

Role checks are performed at every API route after workspace context is resolved:

```typescript theme={null}
export async function DELETE(req: NextRequest) {
  // First: establish workspace and role from the authenticated user
  const { workspaceId, role } = await requireSettingsAccess(req, ['owner', 'admin']);
  // Only owners and admins reach this point
  // ...
}
```

The role list passed to `requireSettingsAccess` defines the minimum required roles. Routes not in the list will receive a 403 response.

### Role Capabilities Reference

| Capability               | operator | developer | admin | owner |
| ------------------------ | -------- | --------- | ----- | ----- |
| View conversations       | ✅        | ✅         | ✅     | ✅     |
| Send messages            | ✅        | ✅         | ✅     | ✅     |
| Manage contacts          | ✅        | ✅         | ✅     | ✅     |
| Configure integrations   | ❌        | ✅         | ✅     | ✅     |
| Manage API keys          | ❌        | ✅         | ✅     | ✅     |
| Manage workspace members | ❌        | ❌         | ✅     | ✅     |
| Configure AI providers   | ❌        | ✅         | ✅     | ✅     |
| Access audit logs        | ❌        | ❌         | ✅     | ✅     |
| Delete workspace         | ❌        | ❌         | ❌     | ✅     |

## API Key Management

### Key Lifecycle

API keys allow programmatic access to Switchbord's API. Each key is:

1. **Generated** with a cryptographically random value
2. **Hashed** with SHA-256 before storage — the plaintext is shown once at creation
3. **Scoped** to the creating workspace — cannot be used to access other workspaces
4. **Optionally expiring** — `expires_at` is enforced at validation time

```typescript theme={null}
// Key creation — hash before storing
const rawKey = generateSecureToken();
const hashedKey = sha256(rawKey);
const keyPrefix = rawKey.slice(0, 8); // stored for display identification

await db.insert(apiKeys).values({
  workspaceId,
  hashedKey,
  prefix: keyPrefix,
  expiresAt: options.expiresAt ?? null,
  createdBy: userId,
});

// Return the raw key once — never stored again
return { key: rawKey, prefix: keyPrefix };
```

### Timing-Safe Comparison

API key validation uses `crypto.timingSafeEqual` to prevent timing-based side-channel attacks:

```typescript theme={null}
import { timingSafeEqual } from 'crypto';

function validateApiKey(providedKey: string, storedHash: string): boolean {
  const providedHash = sha256(providedKey);
  const a = Buffer.from(providedHash, 'hex');
  const b = Buffer.from(storedHash, 'hex');

  if (a.length !== b.length) return false;
  return timingSafeEqual(a, b);
}
```

### Key Expiry Enforcement

Keys with an `expires_at` value are rejected at validation time, even if the hash matches:

```typescript theme={null}
if (key.expiresAt && key.expiresAt < new Date()) {
  throw new UnauthorizedError('API key has expired');
}
```

### Key Operations Scoped to Workspace

All key operations (list, delete, revoke) are filtered by the caller's resolved workspace:

```typescript theme={null}
// A developer in workspace A cannot delete workspace B's keys
await db.delete(apiKeys)
  .where(
    and(
      eq(apiKeys.id, keyId),
      eq(apiKeys.workspaceId, workspaceId) // derived from auth, not request body
    )
  );
```

## Compliance Mapping

| Standard  | Control                                       | Implementation                                      |
| --------- | --------------------------------------------- | --------------------------------------------------- |
| ISO 27001 | A.9.2 — User access management                | Invite-only model, role-based provisioning          |
| ISO 27001 | A.9.3 — User responsibilities                 | Password policy enforced at platform level          |
| ISO 27001 | A.9.4 — System and application access control | RBAC at every API route                             |
| ISO 27001 | A.9.4.3 — Password management system          | Min 12 chars, uppercase + digit required            |
| HIPAA     | §164.312(d) — Person or entity authentication | Session validation + API key auth on all routes     |
| HIPAA     | §164.312(a)(1) — Access control               | RBAC with least-privilege role assignments          |
| SOC 2     | CC6.1 — Logical access controls               | Workspace-scoped RBAC enforced server-side          |
| SOC 2     | CC6.2 — System credential management          | API key hashing, prefix display, expiry enforcement |
| SOC 2     | CC6.3 — Role-based access                     | Four-role hierarchy enforced at all routes          |

<Tip>
  For the full compliance control mapping, see the [Compliance Matrix](/security/compliance-matrix).
</Tip>
