# How Unified API Key Authentication Works in FreeLLMAPI: A Technical Deep Dive

> Learn how FreeLLMAPI unified API key authentication works. Our technical deep dive explains secure validation for OpenAI and Anthropic style keys against a persistent secret.

- Repository: [Tashfeen/freellmapi](https://github.com/tashfeenahmed/freellmapi)
- Tags: deep-dive
- Published: 2026-06-28

---

**FreeLLMAPI validates all requests to its `/v1` proxy endpoints using a single unified API key that supports both OpenAI-style bearer tokens and Anthropic-style headers, verifying them through a timing-safe cryptographic comparison against a secret stored in SQLite.**

FreeLLMAPI is an open-source LLM aggregation proxy that standardizes access to multiple providers behind a single interface. The unified API key authentication system serves as the gatekeeper for all public endpoints, ensuring that only authorized clients can access the underlying model APIs. This article examines the implementation details found in the `tashfeenahmed/freellmapi` repository, breaking down exactly how the server extracts, retrieves, and validates credentials without exposing provider secrets.

## The Three-Step Authentication Flow

The authentication system consists of three tightly-coupled components that execute sequentially for every incoming request to protected routes like `/v1/chat/completions` or `/v1/models`.

### Step 1: Extracting the Bearer Token

When a request reaches the proxy router, the `extractApiToken` function in [`server/src/routes/proxy.ts`](https://github.com/tashfeenahmed/freellmapi/blob/main/server/src/routes/proxy.ts) (lines 52-66) inspects the headers to locate the credential. The implementation supports two common authentication patterns used by major LLM providers.

```typescript
export function extractApiToken(req: Request): string | undefined {
  const bearer = req.headers.authorization?.replace(/^Bearer\s+/i, '').trim();
  if (bearer) return bearer;

  const apiKeyHeader = req.headers['x-api-key'];
  const xApiKey = Array.isArray(apiKeyHeader) ? apiKeyHeader[0] : apiKeyHeader;
  return xApiKey?.trim() || undefined;
}

```

This function checks for an `Authorization` header with a Bearer prefix, falling back to the `x-api-key` header used by Anthropic-style clients. If neither header is present, the function returns `undefined` and the request fails authentication.

### Step 2: Retrieving the Stored Unified Key

The unified API key persists in the SQLite database under the `settings` table with the key name `unified_api_key`. The `getUnifiedApiKey` function in [`server/src/db/index.ts`](https://github.com/tashfeenahmed/freellmapi/blob/main/server/src/db/index.ts) (lines 80-84) retrieves this value:

```typescript
export function getUnifiedApiKey(): string {
  const db = getDb();
  const row = db.prepare("SELECT value FROM settings WHERE key = 'unified_api_key'").get() as { value: string };
  return row.value;
}

```

The key is generated once during database initialization via `regenerateUnifiedKey()`, which creates a random string prefixed with `freellmapi-`. This single key protects all proxy endpoints, eliminating the need for per-user API key management for client access.

### Step 3: Timing-Safe Validation

To prevent timing attacks that could leak the key through response time analysis, FreeLLMAPI avoids direct string comparison (`===`). Instead, it uses `timingSafeStringEqual` in [`server/src/routes/proxy.ts`](https://github.com/tashfeenahmed/freellmapi/blob/main/server/src/routes/proxy.ts) (lines 38-50):

```typescript
export function timingSafeStringEqual(provided: string, expected: string): boolean {
  const key = Buffer.alloc(32);
  const a = crypto.createHmac('sha256', key).update(provided).digest();
  const b = crypto.createHmac('sha256', key).update(expected).digest();
  return crypto.timingSafeEqual(a, b);
}

```

This function generates a hidden 256-bit HMAC key, hashes both the provided and expected tokens, and uses Node.js's `crypto.timingSafeEqual` to compare the digests in constant time. This approach ensures that attackers cannot determine how many characters of their guess are correct based on server response times.

## Endpoint Enforcement

Every public proxy handler implements the authentication guard before processing requests. For example, the `/models` endpoint in [`server/src/routes/proxy.ts`](https://github.com/tashfeenahmed/freellmapi/blob/main/server/src/routes/proxy.ts) demonstrates the complete validation sequence:

```typescript
proxyRouter.get('/models', (req, res) => {
  const token = extractApiToken(req);
  const unifiedKey = getUnifiedApiKey();
  if (!token || !timingSafeStringEqual(token, unifiedKey)) {
    res.status(401).json({ error: { message: 'Invalid API key', type: 'authentication_error' } });
    return;
  }
  // ...continue building the model catalog...
});

```

The same validation pattern appears in all chat completion and model listing routes, ensuring consistent protection across the entire API surface.

## Client Usage Examples

Clients can authenticate using either the OpenAI-style `Authorization` header or the Anthropic-style `x-api-key` header.

**OpenAI-Style Bearer Token:**

```bash
curl https://api.your-domain.com/v1/chat/completions \
  -H "Authorization: Bearer YOUR_UNIFIED_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
        "model": "gpt-4o-mini",
        "messages": [{ "role": "user", "content": "Hello!" }]
      }'

```

**Anthropic-Style API Key:**

```bash
curl https://api.your-domain.com/v1/chat/completions \
  -H "x-api-key: YOUR_UNIFIED_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
        "model": "gpt-4o-mini",
        "messages": [{ "role": "user", "content": "Hello!" }]
      }'

```

Both requests succeed only if the header value matches exactly the unified key stored in the SQLite database.

## Key Management and Regeneration

Administrators can regenerate the unified API key using the `regenerateUnifiedKey` function from [`server/src/db/index.ts`](https://github.com/tashfeenahmed/freellmapi/blob/main/server/src/db/index.ts):

```typescript
import { regenerateUnifiedKey } from './server/src/db/index.js';

const newKey = regenerateUnifiedKey();
console.log('New unified API key:', newKey);

```

**Important:** Regeneration immediately invalidates all existing client tokens. You must distribute the new key to all clients before they can access the API again.

## Summary

- **FreeLLMAPI uses a single unified API key** stored in SQLite to authenticate all requests to its `/v1` proxy endpoints.
- **Dual header support** allows clients to authenticate via `Authorization: Bearer` or `x-api-key` headers, maximizing compatibility with OpenAI and Anthropic SDKs.
- **Timing-safe comparison** via `crypto.timingSafeEqual` prevents side-channel attacks that could expose the key through response timing analysis.
- **Centralized enforcement** in [`server/src/routes/proxy.ts`](https://github.com/tashfeenahmed/freellmapi/blob/main/server/src/routes/proxy.ts) ensures every public endpoint validates credentials before processing requests.

## Frequently Asked Questions

### Where is the unified API key stored in FreeLLMAPI?

The unified API key resides in the SQLite database's `settings` table under the key name `unified_api_key`. The `getUnifiedApiKey()` function in [`server/src/db/index.ts`](https://github.com/tashfeenahmed/freellmapi/blob/main/server/src/db/index.ts) retrieves this value, and it is generated automatically during database initialization if not present.

### How does FreeLLMAPI prevent timing attacks on API keys?

Instead of using direct string comparison (`===`), FreeLLMAPI hashes both the provided and expected keys using HMAC-SHA256 with a random 256-bit buffer, then compares the digests using Node.js's `crypto.timingSafeEqual()`. This ensures the comparison takes constant time regardless of how many characters match, preventing attackers from guessing the key byte-by-byte through timing analysis.

### Can I use standard OpenAI client libraries with FreeLLMAPI?

Yes. FreeLLMAPI's `extractApiToken` function specifically supports the `Authorization: Bearer <token>` format used by OpenAI SDKs. You can configure standard OpenAI clients to point to your FreeLLMAPI instance and provide the unified API key as the bearer token.

### What happens when I regenerate the unified API key?

Calling `regenerateUnifiedKey()` creates a new random key prefixed with `freellmapi-` and stores it in the database, immediately invalidating the previous key. All existing client requests will receive `401 Invalid API key` responses until they are updated with the new credential.