How Cloudflare Access Gates the `/mcp` Route and Which Headers `resolveUserContextFromHeaders` Uses
resolveUserContextFromHeaders secures the /mcp endpoint by validating Cloudflare Access headers—specifically CF-Access-Authenticated-User-Email, CF-Access-Authenticated-User-Name, CF-Access-Authenticated-User-Id, and CF-Access-Client-Id—to build a trusted user context in the every-app/open-seo repository.
The every-app/open-seo repository implements Zero Trust security for its Managed Control Panel (MCP) by gating the /mcp route through Cloudflare Access. When a request arrives, the server invokes resolveUserContextFromHeaders (located in src/middleware/ensure-user/resolve.ts) to extract identity metadata from Cloudflare-specific headers. This centralized approach ensures that only authenticated users with valid Cloudflare Access tokens can interact with MCP resources.
Gating the /mcp Route Through Middleware
Transport Layer Integration
In src/server/mcp/transport.ts (around line 225), the MCP handler creation process begins by resolving the user context before executing any business logic. The transport layer imports the resolution helper and awaits the user context, effectively blocking unauthorized requests at the edge.
// src/server/mcp/transport.ts
import { resolveUserContextFromHeaders } from "@/middleware/ensure-user/resolve";
async function handleRequest(request: Request) {
const userContext = await resolveUserContextFromHeaders(request.headers);
// Proceed only if userContext is valid
}
Delegation to the Cloudflare Access Resolver
The resolveUserContextFromHeaders function acts as a thin wrapper that delegates to resolveCloudflareAccessContext inside src/middleware/ensure-user/cloudflareAccess.ts (export declaration around line 39). This module checks if the deployment runs in Cloudflare Access mode via isCloudflareAccessMode(), then parses the identity headers to construct a normalized UserContext object.
Headers Consumed by resolveUserContextFromHeaders
The actual header extraction occurs in src/middleware/ensure-user/cloudflareAccess.ts between lines 50 and 80. The resolver specifically looks for Cloudflare Access identity headers prefixed with CF-Access-.
Required Cloudflare Access Identity Headers
The function requires the following headers to build a complete user profile:
CF-Access-Authenticated-User-Email– The verified email address of the authenticated user.CF-Access-Authenticated-User-Name– The display name associated with the Cloudflare Access identity.CF-Access-Authenticated-User-Id– A unique identifier generated by Cloudflare for the user.CF-Access-Client-Id– The client identifier associated with the Access application.
Optional Authorization Header
In some configurations, the resolver also inspects the standard Authorization header for a Bearer token containing the Cloudflare Access JWT. This provides a fallback or additional validation layer when the CF-Access headers are not directly available.
Practical Implementation Example
Below is a condensed example demonstrating how to manually invoke the resolver for testing or custom middleware purposes.
// Example: Manually resolving user context from Cloudflare Access headers
import { resolveUserContextFromHeaders } from "@/middleware/ensure-user/resolve";
async function authenticateRequest(request: Request) {
try {
const context = await resolveUserContextFromHeaders(request.headers);
console.log("Authenticated user:", context.email);
return context;
} catch (error) {
throw new Error("Invalid Cloudflare Access headers");
}
}
// Simulating headers from Cloudflare Access
const mockHeaders = new Headers({
"CF-Access-Authenticated-User-Email": "user@example.com",
"CF-Access-Authenticated-User-Name": "Example User",
"CF-Access-Authenticated-User-Id": "user-12345",
"CF-Access-Client-Id": "app-client-id-67890",
});
authenticateRequest(new Request("https://example.com/mcp", { headers: mockHeaders }));
Key Source Files
| File | Purpose | Location |
|---|---|---|
src/server/mcp/transport.ts |
MCP transport entry point; invokes user context resolution before handling requests. | src/server/mcp/transport.ts |
src/middleware/ensure-user/resolve.ts |
Entry point for resolveUserContextFromHeaders; delegates to Cloudflare-specific logic. |
src/middleware/ensure-user/resolve.ts |
src/middleware/ensure-user/cloudflareAccess.ts |
Core implementation of resolveCloudflareAccessContext; parses CF-Access headers around lines 50-80. |
src/middleware/ensure-user/cloudflareAccess.ts |
The transport layer depends on the middleware layer to ensure that every request to /mcp carries valid Cloudflare Access credentials before any MCP method is executed.
Summary
- The
/mcproute is protected by Cloudflare Access middleware that intercepts every request insrc/server/mcp/transport.ts. resolveUserContextFromHeadersserves as the primary entry point for extracting identity data, delegating toresolveCloudflareAccessContext.- The resolver consumes four specific Cloudflare Access headers:
CF-Access-Authenticated-User-Email,CF-Access-Authenticated-User-Name,CF-Access-Authenticated-User-Id, andCF-Access-Client-Id. - An optional
Authorizationheader may also be evaluated for Bearer token validation. - This architecture centralizes authentication logic, ensuring consistent user context across the MCP server.
Frequently Asked Questions
What is the role of resolveUserContextFromHeaders in the Open SEO codebase?
resolveUserContextFromHeaders is the main interface for extracting authenticated user details from incoming request headers. Located in src/middleware/ensure-user/resolve.ts, it forwards header processing to resolveCloudflareAccessContext, which specifically handles Cloudflare Access identity headers. This design keeps the transport layer agnostic of the specific identity provider while enforcing strict authentication at the edge.
Which specific headers does the resolver check to identify a user?
The resolver checks for CF-Access-Authenticated-User-Email, CF-Access-Authenticated-User-Name, CF-Access-Authenticated-User-Id, and CF-Access-Client-Id. These headers are injected by Cloudflare Access after successful authentication. The resolver may also inspect the Authorization header for a JWT Bearer token in certain deployment scenarios.
How does the MCP transport layer enforce Cloudflare Access authentication?
In src/server/mcp/transport.ts (approximately line 225), the MCP handler awaits resolveUserContextFromHeaders before executing any MCP logic. If the resolver fails to validate the headers or the headers are missing, the request is rejected before reaching the business logic layer, effectively gating the entire /mcp route.
Can resolveUserContextFromHeaders be used outside of the MCP transport?
Yes. While primarily used to secure the /mcp endpoint, the function is exported from the middleware module and can be imported into any route handler or worker script within the repository. This allows other sensitive endpoints to leverage the same Cloudflare Access validation logic without duplicating code.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →