Backend JSRuntime GuidesBun
Bun HTTP Handlers
Protect Bun Request handlers and call backend APIs safely.
This guide covers both auth modes in Bun handlers: JWT/session auth and API key/OAuth protected machine-token auth.
Project structure
Bun Service
src/
server.ts
auth/
jwt-auth.ts
machine-auth.ts
handlers/
users.ts
machine-users.ts
1. JWT/session auth handler
import { authenticateRequest, initClient, users } from '@wacht/backend';
initClient({ apiKey: process.env.WACHT_API_KEY! });
export default {
async fetch(request: Request) {
try {
const { auth } = await authenticateRequest(request, {
publishableKey: process.env.WACHT_PUBLISHABLE_KEY,
});
await auth.protect({ permission: 'user:read' });
const page = await users.listUsers({ limit: 20 });
return new Response(JSON.stringify(page), {
headers: { 'content-type': 'application/json' },
});
} catch {
return new Response(JSON.stringify({ error: 'forbidden' }), {
status: 403,
headers: { 'content-type': 'application/json' },
});
}
},
};2. API key/OAuth protected auth for machine tokens
import { gateway, users } from '@wacht/backend';
export async function handleMachineRequest(apiKey: string) {
const decision = await gateway.checkPrincipalAuthz(
{
principalType: 'api_key',
principalValue: apiKey,
resource: '/admin/users',
method: 'GET',
requiredPermissions: ['user:read'],
},
);
if (!decision.allowed) {
return new Response(JSON.stringify({ error: 'forbidden' }), {
status: 403,
headers: { 'content-type': 'application/json' },
});
}
const page = await users.listUsers({ limit: 20 });
return new Response(JSON.stringify(page), {
headers: { 'content-type': 'application/json' },
});
}Bun deployment notes
- Keep env injection in Bun runtime config, not source code.
- Centralize permission constants for consistency across endpoints.
- Keep list calls bounded (
limit) to avoid large response payloads. - Log authorization
request_idfor machine-token support/debug flows. gatewayUrlis optional; custom host overrides are available on Enterprise plans.