edge-oauth-client
An edge-compatible ATProto OAuth client for Cloudflare Workers. Extends @atproto/oauth-client with WebCrypto-based cryptography, edge-friendly DID and handle resolution, and Cloudflare Workers compatibility patches.
Installation
bash
npm install @atiproto/edge-oauth-client @atiproto/kv-oauth-state-store
You will also need @atproto/oauth-client as a peer dependency.
Quick Setup
Call patchGlobalRequestObject() once at the top of your Worker entrypoint, then create an EdgeOAuthClient with your KV-backed state and session stores:
typescript
import { EdgeOAuthClient, patchGlobalRequestObject } from "@atiproto/edge-oauth-client";import { KvStateStore, KvSessionStore } from "@atiproto/kv-oauth-state-store";// Required once — strips unsupported Request.cache property for WorkerspatchGlobalRequestObject();interface Env {OAUTH_STATE_KV: KVNamespace;OAUTH_SESSION_KV: KVNamespace;}function createOAuthClient(env: Env) {return new EdgeOAuthClient({clientMetadata: {client_id: "https://your-app.example.com/oauth/client-metadata.json",client_name: "My App",client_uri: "https://your-app.example.com",redirect_uris: ["https://your-app.example.com/oauth/callback"],grant_types: ["authorization_code", "refresh_token"],response_types: ["code"],scope: "atproto transition:generic",token_endpoint_auth_method: "none",application_type: "web",dpop_bound_access_tokens: true,},stateStore: new KvStateStore(env.OAUTH_STATE_KV),sessionStore: new KvSessionStore(env.OAUTH_SESSION_KV),});}
Authorization Flow
Start login
typescript
async function handleLogin(request: Request, env: Env) {const client = createOAuthClient(env);const handle = new URL(request.url).searchParams.get("handle");const url = await client.authorize(handle, {scope: "atproto transition:generic",});return Response.redirect(url.toString());}
Handle callback
typescript
async function handleCallback(request: Request, env: Env) {const client = createOAuthClient(env);const { session } = await client.callback(new URL(request.url).searchParams);// Store session.did in a cookie or session storereturn new Response(JSON.stringify({ did: session.did }));}
Restore a session
typescript
async function handleApiRequest(request: Request, env: Env) {const client = createOAuthClient(env);const session = await client.restore("did:plc:user123");// session.fetchHandler is an authenticated fetchreturn session.fetchHandler("https://bsky.social/xrpc/app.bsky.actor.getProfile",{ method: "GET" });}
Related Packages
- @atiproto/kv-oauth-state-store — Cloudflare KV-backed
stateStoreandsessionStoreimplementations - @atiproto/edge-resolvers — Edge-compatible DID and handle resolvers (used as defaults internally; override via constructor options)
- @atiproto/edge-resolver-cache — Tiered Cache API + in-memory resolver caching
Classes
- EdgeOAuthClient — Main OAuth client; constructor options and defaults
- EdgeRuntimeImplementation — WebCrypto-based RuntimeImplementation for edge runtimes
- getKeyset — Builds and caches a Keyset from a private JWK for confidential clients
- getKeyset — Builds and caches a Keyset from a private JWK for confidential clients
- patchGlobalRequestObject — Patches globalThis.Request to strip unsupported cache property