Skip to content

Auth Middleware

Routes can carry an auth middleware. The REST handler awaits it and returns 403 when it fails. This is a deliberate security guarantee.

router.get("/users/me", {
plan: db.from(users).where("id", "=", (ctx) => ctx.userId)._plan,
auth: async (req) => {
const token = req.headers.authorization?.replace("Bearer ", "");
if (!token) return false;
const r = await auth.authenticate(token);
return r.ok; // true = allowed
},
});
const out = await handle(restReq);
if ("status" in out && out.status === 403) {
return res.status(403).json(out.body); // { error: "Forbidden" }
}

If auth throws or returns false, the handler short-circuits with 403. The request never reaches the query.

For row-level scoping, combine route auth with an RLS policy:

const scoped = applyPolicy(db.from(files), allowOwner("ownerId"), ctx);
router.get("/files", { plan: scoped._plan, auth: requireUser });
  • Return false (not throw) for “not authorized” — reserve throws for errors.
  • Combine auth middleware with RLS for defense in depth.
  • Centralize auth in one middleware factory and reuse it.
  • Forgetting to await the handler — auth runs too late.
  • Only checking auth in handlers, not at the route level.