Auth with JsonToken
Issue tokens on a public login route; protect later routes with .use() and typed context.
Prerequisites
JWT_SECRET(or any secret string) in the environment- Register public routes before
.use(authenticate)so they stay open
Tokens and middleware
import {
HttpServer,
JsonToken,
type Middleware,
z,
} from "jsr:@webtools/expressapi";
type Session = { userId: string; role: string };
const tokens = new JsonToken(Deno.env.get("JWT_SECRET") ?? "dev-secret");
const sessionSchema = z.object({ userId: z.string(), role: z.string() });
const authenticate: Middleware<{ session: Session }> = async (req, res) => {
const header = req.headers.get("authorization");
if (!header?.startsWith("Bearer ")) {
return res.status(401).json({ error: "Missing authorization header" });
}
const session = await tokens.verify(header.slice(7), sessionSchema);
if (!session) return res.status(401).json({ error: "Invalid token" });
req.data.session = session;
};
const requireAdmin: Middleware<{ isAdmin: boolean }, { session: Session }> = (req, res) => {
if (req.data.session.role !== "admin") {
return res.status(403).json({ error: "Forbidden" });
}
req.data.isAdmin = true;
};Public login, then protected routes
export const server = new HttpServer()
.post("/login", async (req, res) => {
const token = await tokens.sign({ userId: "1", role: "admin" });
return res.json({ token, email: req.body.email });
}, [], {
body: z.object({
email: z.string().email(),
password: z.string().min(6),
}),
})
.use(authenticate)
.get("/profile", (req, res) =>
res.json({ userId: req.data.session.userId }))
.get("/admin", (req, res) =>
res.json({ role: req.data.session.role }), [requireAdmin]);
export type AppRouter = typeof server;