# middleware/require-auth ## Purpose `requireAuth()` is the canonical Hono middleware factory for gating a route or sub-route on an authenticated principal. It reads `c.get("user")` and, if the value is `null` (or absent), throws `AuthError(AUTH_UNAUTHENTICATED)` carrying `context.statusCode: 401` so the `@suaveplan/api` error-handler middleware translates it to an HTTP 401 response. ## Features - Depends only on the typed `c.get("user")` slot installed by `sessionMiddleware` — no dynamic service lookup, no per-request Better-Auth call. - Single failure mode: `AUTH_UNAUTHENTICATED` with `statusCode: 401` attached to the error context. - Idempotent — applying the middleware twice in the same chain costs one type narrow + one truthy check. ## Usage: Basic ```ts import { requireAuth } from "@suaveplan/api-plugin-auth/middleware/require-auth"; app.use("/private/*", requireAuth()); app.get("/private/me", (c) => c.json(c.get("user"))); ``` ## Usage: Advanced Compose `requireAuth` with `requireRole` and `requireEmailVerified` to build a sliding scale of access controls. Each middleware throws its own typed `AuthError`, so the error handler can emit specific OpenAPI 4xx responses per stage: ```ts import { requireAuth, requireRole, requireEmailVerified, } from "@suaveplan/api-plugin-auth/middleware"; app.use("/admin/*", requireAuth(), requireRole("admin")); app.use("/billing/*", requireAuth(), requireEmailVerified()); ``` ## API Reference ### `function requireAuth(): MiddlewareHandler` Returns a Hono middleware handler. Throws `AuthError(AUTH_UNAUTHENTICATED, "Authentication required", { context: { statusCode: 401 } })` when `c.get("user")` is null or undefined. Calls `next()` otherwise. ## Implementation Notes - The check uses `=== null || === undefined` rather than a truthy check so a fully-populated `Principal` with falsy values (e.g. `email: ""` after the principal mapping normalised it out) still passes. `Principal` objects are never falsy. - Throwing — not returning a 401 response directly — keeps the error shape consistent with `requireRole` and `requireEmailVerified`; all three flow through the `@suaveplan/api` error-handler, which both serialises the error envelope and emits the OTel span event. - The `statusCode: 401` field is read by the error-handler middleware installed by `@suaveplan/api`; the auth plugin does not own status mapping itself.