# Security Measures That Protect API Key and OAuth Authentication in Context7

> Discover how Context7 secures API key and OAuth authentication with mandatory validation, Bearer token transmission, RFC-compliant discovery, and JWT verification for robust protection.

- Repository: [Upstash/context7](https://github.com/upstash/context7)
- Tags: best-practices
- Published: 2026-02-16

---

**Context7 implements a layered security model that safeguards both API‑key and OAuth 2.0 authentication through mandatory validation, Bearer token transmission, RFC‑compliant discovery endpoints, and cryptographic JWT verification.**

The Context7 SDK and MCP server (from the `upstash/context7` repository) employ multiple defensive layers to ensure that **API‑key** and **OAuth** credentials remain secure during transmission, validation, and storage. These security measures protect API key and OAuth authentication in Context7 by combining client‑side checks, server‑side extraction logic, and standards‑based token verification.

## API Key Security Measures in Context7

### Mandatory Key Validation and Format Checking

The SDK enforces strict API‑key hygiene before any network request is attempted. In [`packages/sdk/src/client.ts`](https://github.com/upstash/context7/blob/main/packages/sdk/src/client.ts), the constructor validates that a key is present either via the `apiKey` option or the `CONTEXT7_API_KEY` environment variable. If neither is found, it throws a `Context7Error`.

```typescript
// packages/sdk/src/client.ts L21-L28
if (!apiKey) {
  throw new Context7Error("API key is required. Provide it via the apiKey option or CONTEXT7_API_KEY environment variable.");
}

```

Additionally, the SDK warns developers when the key does not start with the expected `ctx7sk` prefix, helping catch accidental paste errors or placeholder strings before they reach the server.

```typescript
// packages/sdk/src/client.ts L30-L32
if (!apiKey.startsWith(API_KEY_PREFIX)) {
  console.warn(`API key should start with '${API_KEY_PREFIX}'`);
}

```

### Secure Bearer Token Transmission

Once validated, the API key is never sent as a query parameter or in the request body. Instead, the SDK attaches it as a **Bearer token** in the `Authorization` header for every HTTP request.

```typescript
// packages/sdk/src/client.ts L35-L38
headers: {
  Authorization: `Bearer ${apiKey}`,
  ...
}

```

This ensures the credential travels encrypted inside the TLS tunnel and remains invisible to server logs that might record URL query strings.

### Server-Side Key Extraction Flexibility

The MCP server ([`packages/mcp/src/index.ts`](https://github.com/upstash/context7/blob/main/packages/mcp/src/index.ts)) accepts API keys from multiple header locations to accommodate diverse client libraries while maintaining security. It checks `Authorization` (Bearer), `context7-api-key`, and `x-api-key` headers, extracting the first valid credential found.

```typescript
// packages/mcp/src/index.ts L10-L15
const extractApiKey = (req) =>
  extractBearerToken(req.headers.authorization) ||
  extractHeaderValue(req.headers["context7-api-key"]) ||
  extractHeaderValue(req.headers["x-api-key"]) ||
  ...;

```

This layered extraction ensures compatibility without forcing clients to modify their existing header conventions.

## OAuth 2.0 Authentication Security in Context7

### OAuth Discovery and Metadata Endpoints

Context7 implements **RFC 9728** (OAuth 2.0 Protected Resource Metadata) to allow automatic discovery of authorization server configuration. When a client accesses `/mcp/oauth`, the server responds with a `WWW-Authenticate` header pointing to the metadata endpoint.

```typescript
// packages/mcp/src/index.ts L30-L34
res.set("WWW-Authenticate", `Bearer resource_metadata="${baseUrl}/.well-known/oauth-protected-resource"`);

```

The metadata endpoint (`/.well-known/oauth-protected-resource`) publishes the resource URL, supported scopes, and the location of the authorization server, enabling clients to configure themselves without hardcoding URLs.

### JWT Validation and Remote JWKS Verification

When the MCP server receives a token that appears to be a JWT (three dot-separated parts), it delegates validation to [`packages/mcp/src/lib/jwt.ts`](https://github.com/upstash/context7/blob/main/packages/mcp/src/lib/jwt.ts). This module performs full cryptographic verification:

1. **Signature validation** against the remote JSON Web Key Set (JWKS) hosted by Clerk.
2. **Issuer and audience checks** to ensure the token was issued by the trusted identity provider.
3. **Expiration verification** to reject stale tokens.

```typescript
// packages/mcp/src/lib/jwt.ts L14-L38
export async function validateJWT(token: string): Promise<JWTValidationResult> {
  // Fetch JWKS from Clerk
  const jwks = await fetchJWKS();
  // Verify signature, exp, iss, aud
  const result = await verifyToken(token, jwks);
  return result;
}

```

Invalid or expired tokens result in an immediate `401 Unauthorized` JSON-RPC error, preventing unauthorized access to protected resources.

### Protected Endpoint Access Control

The `/mcp/oauth` endpoint explicitly requires authentication. The server checks for either a valid API key or a verified JWT before processing any JSON-RPC requests. Unauthenticated requests receive a clear error message indicating the missing credentials.

```typescript
// packages/mcp/src/index.ts L36-L44
if (!apiKey) {
  return res.status(401).json({
    jsonrpc: "2.0",
    error: { code: -32001, message: "Unauthorized: API key or valid JWT required" }
  });
}

```

This strict boundary ensures that sensitive operations (library indexing, private data retrieval) are never exposed to anonymous traffic.

## Environment Variable Security for API Keys

To prevent accidental credential leakage in source code, the SDK automatically falls back to the `CONTEXT7_API_KEY` environment variable when no explicit `apiKey` option is provided. This encourages deployment patterns where keys are injected by secret managers (GitHub Actions secrets, AWS Secrets Manager, or Docker secrets) rather than hardcoded in configuration files.

```typescript
// packages/sdk/src/client.ts L22
const apiKey = options.apiKey ?? process.env.CONTEXT7_API_KEY;

```

If the environment variable is also missing, the constructor throws immediately, failing closed rather than attempting unauthenticated requests.

## Summary

- **Mandatory validation** – The SDK requires API keys at construction time and validates the `ctx7sk` prefix to catch configuration errors early.
- **Bearer token transport** – All credentials travel as `Authorization: Bearer` headers over HTTPS, never in URLs or bodies.
- **Flexible server extraction** – The MCP server accepts keys from multiple header locations while maintaining strict validation.
- **RFC 9728 compliance** – OAuth discovery endpoints enable automatic configuration of authorization servers.
- **Cryptographic JWT verification** – Remote JWKS validation ensures tokens are genuine, unexpired, and issued by trusted identity providers.
- **Environment variable support** – The SDK encourages secure key injection via `CONTEXT7_API_KEY` to prevent hardcoded secrets.

## Frequently Asked Questions

### How does Context7 validate API key format?

Context7 validates API keys through a two-step process in [`packages/sdk/src/client.ts`](https://github.com/upstash/context7/blob/main/packages/sdk/src/client.ts). First, it checks for the presence of a key either via the constructor option or the `CONTEXT7_API_KEY` environment variable, throwing a `Context7Error` if neither exists. Second, it verifies that the key starts with the `ctx7sk` prefix, logging a warning if the format appears incorrect to help developers catch typos or placeholder values before they reach the server.

### What OAuth 2.0 standards does Context7 implement?

Context7 implements **RFC 9728** (OAuth 2.0 Protected Resource Metadata) to enable automatic discovery of authorization server configuration. The MCP server exposes a `/.well-known/oauth-protected-resource` endpoint that publishes the resource identifier, supported scopes, and authorization server location. Additionally, the server uses standard **JWT** validation per RFC 7519, verifying signatures against remote JSON Web Key Sets (JWKS) to ensure token integrity.

### How does Context7 prevent API key exposure in code?

Context7 prevents API key exposure by supporting environment-variable-based configuration through the `CONTEXT7_API_KEY` variable. When instantiating the client without an explicit `apiKey` option, the SDK automatically reads this environment variable, allowing developers to inject secrets via CI/CD secret stores, Docker secrets, or cloud provider key management services. This pattern eliminates the need to hardcode sensitive strings in source files or configuration repositories.

### What happens when JWT validation fails in Context7?

When JWT validation fails, the MCP server returns a **401 Unauthorized** JSON-RPC error response. The validation process in [`packages/mcp/src/lib/jwt.ts`](https://github.com/upstash/context7/blob/main/packages/mcp/src/lib/jwt.ts) checks the token's cryptographic signature against the remote JWKS from Clerk, verifies the issuer and audience claims, and ensures the token has not expired. If any check fails—whether due to an invalid signature, expired timestamp, or incorrect issuer—the server immediately rejects the request with a clear error message, preventing unauthorized access to protected resources.