Middleware Hono : protéger tes routes privées en tokens

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.

4 min read

Pourquoi ajouter un middleware d’authentification

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 :

  • Code DRY : une seule fonction protège toutes les routes.
  • Lisibilité : ton handler focus sur la logique métier, pas sur la sécurité.
  • Testabilité : le middleware s’isole et se teste unitairement.

Rappel : d’où vient le token ?

Le mini-cours a déjà créé :

  1. Un endpoint de connexion qui renvoie un JWT.
  2. Un utilitaire setAuthCookie() qui stocke le token dans un cookie HttpOnly; Secure.

Le client peut ensuite :

  • envoyer le token dans l’en-tête Authorization: Bearer <token>;
  • ou laisser le navigateur renvoyer le cookie automatiquement.

Le middleware authenticateUserMiddleware

src/middlewares/authenticateUser.ts
1
import { createMiddleware } from "hono/factory";
2
import { HTTPException } from "hono/http-exception";
3
import { getExistingToken } from "../token.js";
4
import { getAuthToken } from "../utils/cookie-utils.js";
5
6
export const authenticateUserMiddleware = createMiddleware(async (c, next) => {
7
const authorizationHeader = c.req.header("Authorization");
8
const cookieToken = getAuthToken(c);
9
10
let token: string | undefined;
11
12
if (authorizationHeader) {
13
token = authorizationHeader.split(" ")[1];
14
} else if (cookieToken) {
15
token = cookieToken;
16
}
17
18
if (!token) {
19
throw new HTTPException(401, {
20
message: "You are not authorized to access this resource",
21
});
22
}
23
24
const existingToken = await getExistingToken({ token });
25
26
if (!existingToken) {
27
throw new HTTPException(401, {
28
message: "You are not authorized to access this resource",
29
});
30
}
31
32
c.set("user", existingToken.user);
33
34
await next();
35
});

Explications pas à pas :

  1. createMiddleware
    La fabrique Hono reçoit ta fonction (c, next) et la branche avant le handler ciblé.

  2. Recherche du token

    • Priorité à l’en-tête Authorization (utile pour les clients mobiles ou Postman).
    • Fallback sur le cookie, plus pratique côté navigateur.
  3. Absence de token
    On lève une HTTPException(401) directement.
    Pourquoi ? On évite d’atteindre le handler, on économise des cycles CPU.

  4. Validation du token
    getExistingToken() interroge la base via Prisma.
    Si le token n’existe plus (logout, expiration manuelle, etc.), on renvoie 401.

  5. 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").

  6. await next()
    On passe la main seulement si toutes les vérifs sont OK.

Brancher le middleware sur tes routes

src/routes/private.ts
1
import { Hono } from "hono";
2
import { authenticateUserMiddleware } from "../middlewares/authenticateUser.ts";
3
4
const privateRoutes = new Hono();
5
6
// applique le middleware a toutes les routes du groupe
7
privateRoutes.use("*", authenticateUserMiddleware);
8
9
privateRoutes.get("/profile", (c) => {
10
const user = c.get("user");
11
return c.json({ id: user.id, email: user.email });
12
});
13
14
export default privateRoutes;

Pourquoi use("*", middleware) ?
Tu assures que toute requête vers ce groupe passe par la vérification d’auth.

Cas d’erreur à tester

1
--- Terminal
2
curl -i localhost:8787/profile
3
--- Result
4
HTTP/1.1 401 Unauthorized
5
{ "error": "You are not authorized to access this resource" }
  1. Sans token : 401 direct.
  2. Avec token invalide : 401.
  3. Avec token valide : 200 et le JSON du profil.

Aller plus loin

  • Chiffrer le token JWT à l’aide d’un secret robuste.
  • Implémenter une date d’expiration et un refresh token.
  • Logger les tentatives d’accès refusées (monitoring).

Conclusion

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.

Quiz

Testez vos connaissances avec 5 questions

1Question 1 sur 5

Pourquoi encapsuler la vérification du token dans un middleware Hono plutôt que de la faire dans chaque handler ?

2Question 2 sur 5

Dans quel ordre le middleware "authenticateUserMiddleware" recherche-t-il un token ?

3Question 3 sur 5

Quelle réponse HTTP est renvoyée lorsque le middleware ne trouve aucun token ou détecte un token invalide ?

4Question 4 sur 5

Quel est l’effet de l’appel c.set("user", existingToken.user) dans le middleware ?

5Question 5 sur 5

Pourquoi le middleware appelle-t-il await next() uniquement après avoir passé toutes les vérifications ?