
Cloudflare Auth
Ship a Hono Cloudflare Worker behind Cloudflare Access with the same auth behavior in production JWT validation and local dev.
Install
npx skills add https://github.com/adrianhall/cloudflare-auth --skill cloudflare-authWhat is this skill?
- developerAuthentication middleware for frictionless local dev without Cloudflare Access in the loop
- cloudflareAccess middleware for production JWT validation via Access-injected headers and CF_Authorization
- Environment-agnostic handlers: both middleware paths agree on the authenticated user shape
- Guidance for path-based policies (public vs protected routes) and static assets served through the Worker
- wrangler.jsonc configuration patterns when auth and static assets share one Worker
Adoption & trust: 1 installs on skills.sh; trending (+100% hot-view momentum).
Recommended Skills
Azure Deploymicrosoft/azure-skills
Azure Preparemicrosoft/azure-skills
Azure Storagemicrosoft/azure-skills
Azure Validatemicrosoft/azure-skills
Appinsights Instrumentationmicrosoft/azure-skills
Azure Resource Lookupmicrosoft/azure-skills
Journey fit
SKILL.md
READMESKILL.md - Cloudflare Auth
## When to Load This Skill Load this skill whenever a developer is: - Building a Hono Worker that will be deployed behind Cloudflare Access - Asking how to do local development against a Cloudflare Access-protected API - Serving protected static assets (frontend) through a Worker (not via wrangler's asset serving alone) - Setting up path-based auth policies (some routes public, some protected) - Asking why `CF_Authorization` cookie is not being set before API calls - Configuring `wrangler.jsonc` for a Worker that handles both auth and static assets --- ## The Core Problem This Library Solves In production, Cloudflare Access injects signed JWT headers and the `CF_Authorization` cookie into every request before they reach your Worker. During local development, those headers are absent — there is no Cloudflare Access in the loop. Without this library, developers either skip auth entirely in dev (risky) or run complex local proxies. **This library solves it with two middleware functions that always agree on the authenticated user:** | Middleware | Production | Local dev | | ------------------------- | ---------------------------------------- | ---------------------------------------------------------------------- | | `developerAuthentication` | **No-op** (JWT header already present) | Drives a one-time-PIN–style login form, sets `CF_Authorization` cookie | | `cloudflareAccess` | Validates JWT via Cloudflare Access JWKS | Validates the same dev-signed JWT via HMAC | --- ## Installation This package is **not published to npm**. Install directly from GitHub (`dist/` is committed): ```bash npm install github:adrianhall/cloudflare-auth#1.0.1 hono # or pnpm add github:adrianhall/cloudflare-auth#1.0.1 hono ``` Peer dependency: `hono ^4.0.0` Runtime dependency: `jose ^6.2.3` (bundled) --- ## Working Example The repository includes a complete diagnostic app in [`example/`](https://github.com/adrianhall/cloudflare-auth/tree/main/example) — a React SPA + Hono API built with the Cloudflare Vite plugin. It exercises every setup pattern documented here (public/protected routes, cookie flow, curl access, production deployment). The configuration recommendations in this skill were determined empirically using the experiments documented in [`example/docs/MANUAL_TESTS.md`](https://github.com/adrianhall/cloudflare-auth/tree/main/example/docs/MANUAL_TESTS.md). When in doubt about a recommendation, refer to the experiment that produced it. --- ## Critical Setup Rules ### 1. Middleware Order Is Non-Negotiable `developerAuthentication` **must always be registered before** `cloudflareAccess`. In production `developerAuthentication` is a no-op, but in dev it injects the headers that `cloudflareAccess` then reads. ```ts // CORRECT app.use(developerAuthentication({ policies })); app.use(cloudflareAccess({ policies })); // WRONG — cloudflareAccess will 401 every dev request app.use(cloudflareAccess({ policies })); app.use(developerAuthentication({ policies })); ``` ### 2. Share the Same Policies Array Define `PathPolicy[]` **once** and pass the identical array to **both** middleware. If the arrays differ, you will get inconsistent behavior where one middleware allows a path the other blocks. ```ts const authPolicies: PathPolicy[] = [ { pattern: /^\/api\/version$/, authenticate: false }, { pattern: /^\/api\//, authenticate: true, redirect: false }, // API: 401 in dev { pattern: /^\/dashboard/, authenticate: true } // Pages: redirect