Auth with Pages Functions
CreatedApr 4, 2026Takeshi Takatsudo
Authentication patterns using Cloudflare Pages Functions
Overview
Pages Functions can handle authentication by integrating with external auth providers (Auth0, etc.) or implementing custom token validation.
Auth0 Integration Pattern
From our zudo-pattern-gen project, using Auth0 with Pages Functions:
Wrangler Config
[vars]
AUTH0_DOMAIN = "your-tenant.us.auth0.com"
AUTH0_CLIENT_ID = "your-client-id"
π¨ Secrets vs Vars
AUTH0_CLIENT_ID is safe in [vars] (itβs public). But AUTH0_CLIENT_SECRET must be set via wrangler secret put AUTH0_CLIENT_SECRET β never in wrangler.toml.
Auth Middleware Function
Create a middleware function that validates tokens:
// functions/auth/_middleware.ts
interface Env {
AUTH0_DOMAIN: string;
AUTH0_CLIENT_ID: string;
}
export const onRequest: PagesFunction<Env> = async (context) => {
const authHeader = context.request.headers.get("Authorization");
if (!authHeader?.startsWith("Bearer ")) {
return new Response("Unauthorized", { status: 401 });
}
const token = authHeader.slice(7);
try {
// Validate token with Auth0
const response = await fetch(
`https://${context.env.AUTH0_DOMAIN}/userinfo`,
{ headers: { Authorization: `Bearer ${token}` } }
);
if (!response.ok) {
return new Response("Unauthorized", { status: 401 });
}
// Token is valid, continue to the next function
return context.next();
} catch {
return new Response("Unauthorized", { status: 401 });
}
};
File-Based Middleware Routing
Pages Functions support _middleware.ts files that run before the actual function:
functions/
βββ auth/
β βββ _middleware.ts # Auth check for all /auth/* routes
β βββ callback.ts
βββ api/
β βββ _middleware.ts # Auth check for all /api/* routes
β βββ data.ts
βββ public/
βββ health.ts # No auth needed
CORS Headers
For API functions called from a different domain:
const corsHeaders = {
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "GET, POST, OPTIONS",
"Access-Control-Allow-Headers": "Content-Type, Authorization",
};
export const onRequestOptions: PagesFunction = async () => {
return new Response(null, { headers: corsHeaders });
};
export const onRequestGet: PagesFunction<Env> = async (context) => {
// ... your logic
return new Response(JSON.stringify(data), {
headers: {
"Content-Type": "application/json",
...corsHeaders,
},
});
};