Backend JSRuntime GuidesHono
Middleware and Auth
Implement reusable Hono auth middleware with permission checks.
This guide implements both auth modes in Hono: JWT/session middleware and API key/OAuth protected checks for machine-token endpoints.
Project shape
Hono Middleware Setup
src/
app.ts
middleware/
auth.ts
routes/
admin.ts
errors.ts
import type { MiddlewareHandler } from 'hono';
import { authenticateRequest } from '@wacht/backend';
export const authMiddleware: MiddlewareHandler = async (c, next) => {
const { auth } = await authenticateRequest(c.req.raw, {
publishableKey: process.env.WACHT_PUBLISHABLE_KEY,
});
await auth.protect({ permission: 'deployment:read' });
c.set('auth', auth);
await next();
};JWT/session-protected routes
import { Hono } from 'hono';
import { users } from '@wacht/backend';
export const adminRoutes = new Hono();
adminRoutes.get('/users', async (c) => {
const data = await users.listUsers({ limit: 20 });
return c.json(data);
});API key/OAuth protected machine route
import { Hono } from 'hono';
import { gateway, users } from '@wacht/backend';
export const machineRoutes = new Hono();
machineRoutes.get('/users', async (c) => {
const incoming = c.req.header('x-api-key') || '';
const decision = await gateway.checkPrincipalAuthz(
{
principalType: 'api_key',
principalValue: incoming,
resource: '/machine/users',
method: 'GET',
requiredPermissions: ['user:read'],
},
);
if (!decision.allowed) {
return c.json({ error: 'forbidden' }, 403);
}
return c.json(await users.listUsers({ limit: 20 }));
});import { Hono } from 'hono';
import { authMiddleware } from './middleware/auth';
import { adminRoutes } from './routes/admin';
import { machineRoutes } from './routes/machine';
const app = new Hono();
app.use('/admin/*', authMiddleware);
app.route('/admin', adminRoutes);
app.route('/machine', machineRoutes);
app.onError((err, c) => c.json({ error: 'internal_error', message: err.message }, 500));
export default app;Production details
- Return JSON errors from a global
app.onErrorhandler. - Keep permission names centralized to avoid drift across middleware and handlers.
- If you proxy through another authorization gateway, preserve the
Authorizationheader end-to-end. - Record
request_idand deny reason in logs for machine-token diagnostics. gatewayUrlis optional; custom host overrides are available on Enterprise plans.