Skip to content
API Reference

Cloudflare Workers

Keycard auth for Cloudflare Workers — JWT verification, token exchange, and isolate-safe caching.

The Cloudflare Workers package adapts Keycard’s OAuth primitives to Workers’ fetch(request, env) handler model. It’s the Workers-native equivalent of @keycardai/mcp (Express).

  • Deploying an MCP server or API on Cloudflare Workers
  • Building Code Mode workers that need Keycard auth
  • Any Worker that needs JWT verification + token exchange with isolate-safe caching
Terminal window
npm install @keycardai/cloudflare

@keycardai/cloudflare

ExportDescription
createKeycardWorkerHigh-level wrapper — chains metadata, auth, and your handler
verifyBearerTokenVerify JWTs from Request — returns AuthInfo or error Response
handleMetadataRequestServes .well-known OAuth endpoints, returns Response or null
IsolateSafeTokenCachePer-user token cache — safe for CF isolate reuse
resolveCredentialAuto-detect credential type from env bindings
WorkersClientSecretApplication credential using client ID + secret
WorkersWebIdentityApplication credential using private key JWT (no secret needed)
import { createKeycardWorker } from "@keycardai/cloudflare";
export default createKeycardWorker({
resourceName: "My MCP Server",
scopesSupported: ["mcp:tools"],
requiredScopes: ["mcp:tools"],
async fetch(request, env, ctx, auth) {
// auth is verified — auth.subject, auth.scopes, auth.token available
return new Response(JSON.stringify({
message: "Hello from Keycard!",
user: auth.subject,
}), {
headers: { "Content-Type": "application/json" },
});
},
});

createKeycardWorker automatically handles:

  • CORS preflight responses
  • OAuth metadata at /.well-known/oauth-protected-resource and /.well-known/oauth-authorization-server
  • Bearer token verification with JWKS, scope checks, and expiration validation
  • JWKS serving at /.well-known/jwks.json when using WebIdentity

Exchange the user’s Keycard token for an upstream API token using IsolateSafeTokenCache:

import {
createKeycardWorker,
IsolateSafeTokenCache,
resolveCredential,
} from "@keycardai/cloudflare";
import { TokenExchangeClient } from "@keycardai/oauth/tokenExchange";
let tokenCache: IsolateSafeTokenCache;
function getCache(env) {
if (!tokenCache) {
const credential = resolveCredential(env);
const client = new TokenExchangeClient(
env.KEYCARD_ISSUER,
credential.getAuth() ?? undefined,
);
tokenCache = new IsolateSafeTokenCache(client, { credential });
}
return tokenCache;
}
export default createKeycardWorker({
async fetch(request, env, ctx, auth) {
const cache = getCache(env);
const token = await cache.getToken(
auth.subject!,
auth.token,
"https://api.github.com",
);
const response = await fetch("https://api.github.com/user", {
headers: { Authorization: `Bearer ${token.accessToken}` },
});
return new Response(await response.text());
},
});

The simplest setup. Create application credentials in Keycard Console and store them as Worker secrets:

Terminal window
wrangler secret put KEYCARD_CLIENT_ID
wrangler secret put KEYCARD_CLIENT_SECRET

No client secret needed. The Worker generates JWT client assertions signed with a private key:

Terminal window
# Generate and store a private key
openssl genrsa 2048 | wrangler secret put KEYCARD_PRIVATE_KEY

The Worker automatically:

  1. Serves its public key at /.well-known/jwks.json
  2. Signs token exchange requests with private_key_jwt (RFC 7523)

Register the Worker’s JWKS URL in Keycard Console as the application’s public key endpoint.

createKeycardWorker auto-detects which mode to use based on which env vars are set.

VariableRequiredDescription
KEYCARD_ISSUERYesKeycard zone URL
KEYCARD_CLIENT_IDOption AApplication client ID
KEYCARD_CLIENT_SECRETOption AApplication client secret
KEYCARD_PRIVATE_KEYOption BPEM-encoded RSA private key
KEYCARD_RESOURCE_URLFor token exchangeUpstream resource URL