-
Notifications
You must be signed in to change notification settings - Fork 1
fetch
Eugene Lazutkin edited this page Jul 17, 2026
·
1 revision
The Fetch port of the middleware family: cognito-toolkit/fetch, for (request: Request) => Promise<Response> servers — Bun.serve, Deno.serve / Deploy, Cloudflare Workers, Hono, and dynamodb-toolkit's createFetchAdapter handlers.
import {makeAuth} from 'cognito-toolkit/fetch';
function makeAuth<Payload extends object = JwtPayload>(options: AuthOptions<Payload>): Auth<Payload>;
type FetchHandler = (request: Request, ...rest: any[]) => Response | Promise<Response>;
interface Auth<Payload> {
getUser(request: Request): Promise<AuthUser<Payload> | null>; // memoized per Request
isAuthenticated(handler: FetchHandler): FetchHandler;
hasGroup(group: string): (handler: FetchHandler) => FetchHandler;
hasScope(scope: string): (handler: FetchHandler) => FetchHandler;
isAllowed(validator: (request: Request, groups: string[], scopes: string[]) => boolean | Promise<boolean>): (handler: FetchHandler) => FetchHandler;
setAuthCookie(request: Request, response: Response, cookieOptions?: CookieOptions): Promise<Response>;
}
type AuthUser<Payload> = Payload & {_token: string};Options: see Middleware ports § Options — no stateUserProperty here. Only standard Request / Response types are involved; the payload type flows from the verifier.
import {CognitoJwtVerifier} from 'cognito-toolkit';
import {makeAuth} from 'cognito-toolkit/fetch';
const verifier = CognitoJwtVerifier.create({userPoolId: 'us-east-1_MY_POOL', clientId: 'my-app-client', tokenUse: 'access'});
const auth = makeAuth({verifier});
export default {
fetch: auth.isAuthenticated(async request => {
const user = await auth.getUser(request); // memoized — already verified by the guard
return Response.json(user);
})
};
// per-route guards wrap individual handlers:
const writers = auth.hasGroup('writers')(async request => new Response('ok'));
// composes directly with dynamodb-toolkit:
// Bun.serve({fetch: auth.isAuthenticated(createFetchAdapter(adapter, {mountPath: '/api'}))});-
Requests are immutable, so there is no state property:getUser(request)is aWeakMap-memoized lookup — guards and handlers share one verification per request, extra calls are free. - Guards preserve extra server args (Bun's
server, Deno'sinfo, Cloudflare'senv/ctx): whatever the server passes afterrequestreaches the wrapped handler untouched. - Denials are
new Response(null, {status: 401 | 403}). -
setAuthCookieis async and returns the response to use — it clones when the original's headers are immutable (e.g. a response obtained fromfetch()). Cookies are serialized in-house:Path=/andHttpOnlyby default,Domainfrom the request hostname.
Start here
Reference
Under the hood