Authorization
Mandatory auth, request context, and public routes.
The authorize function
Every ZenRouter requires an authorize function. It runs before every route
handler. See the Request lifecycle. Return a falsy
value to reject the request with 403 Forbidden. Return any truthy value to
allow the request, and that value becomes available as auth in the handler.
const zen = new ZenRouter
authorize: asyncreq=>
const token =get"Authorization"
const user = awaitgetUserByToken
if!user) return false; // → 403 Forbidden
return
});
zen.route"GET /api/posts", asyncauth=>
// auth.currentUser is fully typed
returngetPostsByUser
});Auth is mandatory by design. This ensures you can never accidentally expose a route without auth.
Public routes
If none of your routes require authentication, explicitly opt out by returning
true.
const zen = new ZenRouter
authorize: () => true,
});
// ⚠️ Now all these routes are public!
zen.route"GET /api/health", ...
zen.route"GET /api/version", ...
zen.route"POST /api/webhooks/stripe", ...The getContext function
getContext is an optional hook for attaching metadata to a request. The return
value becomes available as ctx in every handler and in authorize.
const zen = new ZenRouter
getContext: (req) =>
getDbConnection
createLogger
authorize: asyncreq, ctx=>
info"Checking auth..."
const token =get"Authorization"
const currentUser = awaitgetUserByToken
if!currentUser) return false;
return
});
zen.route
"GET /api/posts/<postId>",
asyncctx, auth, p=>
info`Fetching post ${p.postId}`
returngetPostById
Use context for static metadata like database connections or loggers. Do not
use it for auth: that’s what the mandatory authorize is for.
See the Request lifecycle for a full overview of how a request flows through the router.