Authentication & API Keys
Relevant source files
The following files were used as context for generating this wiki page:
The "Authentication & API Keys" system provides a dual-layered security model for the platform. It supports interactive user sessions via Supabase-managed JSON Web Tokens (JWT) and programmatic access through scoped API keys. This architecture ensures that both the web dashboard and external integrations (such as AI agents or CI/CD pipelines) can securely interact with workspace resources like contacts and email campaigns.
Sources: src/lib/auth.ts:1-125, src/lib/openapi.ts:13-25, README.md:121-127
Authentication Architecture
The system distinguishes between two primary authentication methods. Interactive users authenticate using a standard Bearer token containing a Supabase JWT. Programmatic clients use an API key that starts with the prefix sk_. Both methods are processed through centralized utility functions that validate the identity and resolve the associated workspace context.
Authentication Flow
The following diagram illustrates how the system routes requests based on the provided credentials.
The system uses SHA-256 hashing to store and verify API keys, ensuring that plaintext keys are never stored in the database.
Sources: src/lib/auth.ts:88-144, src/lib/db.ts:108-115, src/lib/db.ts:175-207
Scoped API Keys
API keys are associated with specific workspaces and can be restricted using a set of predefined scopes. This allows developers to grant "least privilege" access to third-party tools.
Available Scopes
| Scope | Description |
|---|---|
contacts.read | Allows listing and retrieving contact details. |
contacts.write | Allows creating, updating, or deleting contacts. |
send.read | Allows checking the status of send jobs and history. |
send.write | Allows initiating new email send jobs. |
Sources: src/app/app/page.tsx:114-119, src/lib/openapi.ts:40-45
API Key Lifecycle
API keys are created within a workspace. Upon creation, the system generates a 32-byte hex string prefixed with sk_. The plaintext key is shown exactly once to the user. Subsequent lookups use a 10-character prefix for identification and a key_hash for authentication.
Technical Implementation Details
Security Schemes
The API specification defines two security schemes used across the REST endpoints.
| Scheme | Type | Description |
|---|---|---|
jwt | HTTP Bearer | Supabase JWT token; required for workspace management and settings. |
apiKey | HTTP Bearer | Starts with sk_; valid for /api/contacts and /api/send endpoints. |
Sources: src/lib/openapi.ts:15-25
Data Structures
The database represents API keys in the api_keys table with the following structure:
Note: The plaintext key_hash is used for authentication lookups but is not part of the public metadata returned to the UI.
Sources: src/lib/db.ts:93-106, src/lib/openapi.ts:31-48
Critical Functions
requireWorkspaceAuth(req, workspaceId, requiredScope): The primary middleware function that handles both JWT and API key validation. It returns the resolved workspace ID and authentication method.hashApiKey(raw): Uses the Web Crypto API (crypto.subtle.digest) to generate a SHA-256 hash of the provided key.getApiKeyAuthByHash(keyHash): Retrieves workspace association and scope permissions from the database using the hashed key.
Sources: src/lib/auth.ts:88-144, src/lib/db.ts:108-115, src/lib/db.ts:175-207
Conclusion
The Authentication & API Keys system ensures that workspace data remains isolated and secure. By combining JWTs for human users with hashed, scoped API keys for machines, the platform provides a flexible yet robust security posture. Developers can manage their keys directly through the workspace settings, revoking access instantly by deleting the key metadata from the database.