Middleware that provides state
Authenticate in middleware, provide a typed user token, and read a frozen snapshot in the handler.
You want your handler to read an authenticated user without re-parsing the auth header, and you want unauthenticated requests rejected with 401 before they reach the handler. Authenticate once in middleware, hand the handler a typed user token, and read a frozen snapshot.
- Define a state token with
flareState. - Write an auth
MiddlewareBasewhosebefore()validates the header, returnsthis.unauthorized(...)on failure, orsets the token on success. List the token instatic provides. - Register with
host.http.use(...). - Read the user with
ctx.state.require(token), declaring it in the route’sstate.
import { FlareHost, FlareResponse, MiddlewareBase, flareState,} from "@flare-ts/core";import { node } from "@flare-ts/core/node";
const AuthUser = flareState<{ id: string; role: "admin" | "user" }>("AuthUser");
class AuthMiddleware extends MiddlewareBase { public static override deps = []; public static override state = []; public static override provides = [AuthUser];
before() { const header = this.ctx.req.headers.get("authorization"); if (header !== "Bearer let-me-in") { return this.unauthorized({ error: "invalid or missing token" }); } this.ctx.state.set(AuthUser, { id: "u1", role: "admin" }); }}
const host = new FlareHost(node);host.http.use(AuthMiddleware);
host.http.get("/me", { state: [AuthUser] }, (ctx) => { const user = ctx.state.require(AuthUser); return new FlareResponse(200, { id: user.id, role: user.role });});
const app = host.build();app.run();Returning a response from before() short-circuits the pipeline: the handler and every after hook are skipped. finally hooks still run. The 401 flows straight back to the client.
Why the wiring holds
Section titled “Why the wiring holds”static provides = [AuthUser] on the middleware and state: [AuthUser] on the route are not just documentation. host.build() verifies that some preceding before() hook provides every token the route reads. Drop the middleware registration and the build fails.
A token is satisfied only by a preceding middleware’s before() provider. Middleware that implements only after or finally does not count.
Controller variant
Section titled “Controller variant”Declare public static override state = [AuthUser] on the controller and read with this.ctx.state.require(AuthUser) inside handler methods.
Mount shared auth on a route group or globally. There is no controller-only middleware slot.