Implémente un middleware Hono en TypeScript pour vérifier JWT et cookie, sécuriser chaque route privée et isoler ta logique métier. Apprends les tests clés.
Une API publique n’a pas besoin de filtre.
Dès que tu exposes des routes privées, tu dois valider l’identité du client avant d’exécuter
ta logique metier.
Avec Hono, la bonne pratique consiste à encapsuler cette vérification dans
un middleware réutilisable.
Avantages immédiats :
Le mini-cours a déjà créé :
setAuthCookie()
qui stocke le token dans un cookie HttpOnly; Secure
.Le client peut ensuite :
Authorization: Bearer <token>
;authenticateUserMiddleware
1import { createMiddleware } from "hono/factory";2import { HTTPException } from "hono/http-exception";3import { getExistingToken } from "../token.js";4import { getAuthToken } from "../utils/cookie-utils.js";56export const authenticateUserMiddleware = createMiddleware(async (c, next) => {7const authorizationHeader = c.req.header("Authorization");8const cookieToken = getAuthToken(c);910let token: string | undefined;1112if (authorizationHeader) {13token = authorizationHeader.split(" ")[1];14} else if (cookieToken) {15token = cookieToken;16}1718if (!token) {19throw new HTTPException(401, {20message: "You are not authorized to access this resource",21});22}2324const existingToken = await getExistingToken({ token });2526if (!existingToken) {27throw new HTTPException(401, {28message: "You are not authorized to access this resource",29});30}3132c.set("user", existingToken.user);3334await next();35});
Explications pas à pas :
createMiddleware
La fabrique Hono reçoit ta fonction (c, next)
et la branche avant le handler ciblé.
Recherche du token
Authorization
(utile pour les clients mobiles ou Postman).Absence de token
On lève une HTTPException(401)
directement.
Pourquoi ? On évite d’atteindre le handler, on économise des cycles CPU.
Validation du token
getExistingToken()
interroge la base via Prisma.
Si le token n’existe plus (logout, expiration manuelle, etc.), on renvoie 401.
Hydratation du contexte
c.set("user", existingToken.user)
ajoute l’utilisateur courant au contexte Hono.
Les handlers en aval y accèdent via c.get("user")
.
await next()
On passe la main seulement si toutes les vérifs sont OK.
1import { Hono } from "hono";2import { authenticateUserMiddleware } from "../middlewares/authenticateUser.ts";34const privateRoutes = new Hono();56// applique le middleware a toutes les routes du groupe7privateRoutes.use("*", authenticateUserMiddleware);89privateRoutes.get("/profile", (c) => {10const user = c.get("user");11return c.json({ id: user.id, email: user.email });12});1314export default privateRoutes;
Pourquoi use("*", middleware)
?
Tu assures que toute requête vers ce groupe passe par la vérification d’auth.
1--- Terminal2curl -i localhost:8787/profile3--- Result4HTTP/1.1 401 Unauthorized5{ "error": "You are not authorized to access this resource" }
Le middleware est central : toute faille ici compromet l’ensemble de l’API. Relis bien le code et écris des tests unitaires ciblés.
Tu viens d’ajouter une barrière de sécurité simple et efficace.
Grâce à ce middleware, chaque route privée vérifie la présence et la validité du token avant
d’exécuter la moindre ligne de logique métier.
Étape suivante du mini-cours : valider les payloads utilisateurs avec Zod.
Testez vos connaissances avec 5 questions
Pourquoi encapsuler la vérification du token dans un middleware Hono plutôt que de la faire dans chaque handler ?
Dans quel ordre le middleware "authenticateUserMiddleware" recherche-t-il un token ?
Quelle réponse HTTP est renvoyée lorsque le middleware ne trouve aucun token ou détecte un token invalide ?
Quel est l’effet de l’appel c.set("user", existingToken.user) dans le middleware ?
Pourquoi le middleware appelle-t-il await next() uniquement après avoir passé toutes les vérifications ?