Skip to content

Middleware that provides state

Authenticate in middleware, provide a typed user token, and read a frozen snapshot in the handler.

AI generated, pending review Updated 10 days ago · Flare 0.3

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.

  1. Define a state token with flareState.
  2. Write an auth MiddlewareBase whose before() validates the header, returns this.unauthorized(...) on failure, or sets the token on success. List the token in static provides.
  3. Register with host.http.use(...).
  4. Read the user with ctx.state.require(token), declaring it in the route’s state.
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.

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.

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.