dpopFetch
uses tcmts.atproto.dpopProof, which uses node:crypto
A request with a DPoP proof (and the access token, when given), made again once with a fresh nonce when the server asks for one, as servers do.
import { dpopNonces, dpopProof } from "#codebase/tcmts/atproto"; import type crypto from "node:crypto"; export async function dpopFetch( key: crypto.JsonWebKey, url: string, init: RequestInit = {}, accessToken?: string, ): Promise<Response> { const origin = new URL(url).origin; const method = init.method ?? "GET"; const send = () => fetch(url, { ...init, headers: { ...Object.fromEntries(new Headers(init.headers)), dpop: dpopProof(key, method, url, dpopNonces.get(origin), accessToken), ...(accessToken ? { authorization: `DPoP ${accessToken}` } : {}), }, }); const res = await send(); const nonce = res.headers.get("dpop-nonce"); if (nonce) dpopNonces.set(origin, nonce); if (!nonce || (res.status !== 400 && res.status !== 401)) return res; const asked = (res.headers.get("www-authenticate") ?? "").includes("use_dpop_nonce") || ( (await res .clone() .json() .catch(() => ({}))) as { error?: string } ).error === "use_dpop_nonce"; return asked ? send() : res; }