Chapitre 1 · Leçon 2
Middleware d'autorisation basé sur les rôles
Section 1
Step 1
Authentification : vérifier qui tu es (JWT). Autorisation : vérifier ce que tu peux faire (RBAC). Ces deux couches sont distinctes.
snippet.typescript
1// types/auth.ts
2export type UserRole = "admin" | "instructor" | "student" | "guest";
3
4export type Permission =
5 | "tutorial:read" | "tutorial:create" | "tutorial:update" | "tutorial:delete"
6 | "user:read" | "user:update" | "user:delete"
7 | "analytics:read";
8
9// Matrice des permissions par rôle
10const ROLE_PERMISSIONS: Record<UserRole, Permission[]> = {
11 admin: [
12 "tutorial:read", "tutorial:create", "tutorial:update", "tutorial:delete",
13 "user:read", "user:update", "user:delete",
14 "analytics:read",
15 ],
16 instructor: [
17 "tutorial:read", "tutorial:create", "tutorial:update",
18 "user:read",
19 ],
20 student: [
21 "tutorial:read",
22 "user:read",
23 ],
24 guest: [
25 "tutorial:read",
26 ],
27};
28
29// Middleware authenticate — vérifie le JWT
30export function authenticate(req: Request, res: Response, next: NextFunction) {
31 const authHeader = req.headers.authorization;
32 if (!authHeader?.startsWith("Bearer ")) {
33 return res.status(401).json({ error: "Token manquant" });
34 }
35 try {
36 const payload = jwt.verify(
37 authHeader.split(" ")[1],
38 process.env.ACCESS_TOKEN_SECRET!
39 ) as JwtPayload;
40 req.user = { id: payload.sub, role: payload.role as UserRole, email: payload.email };
41 next();
42 } catch {
43 res.status(401).json({ error: "Token invalide ou expiré" });
44 }
45}
46
47// Middleware authorize — vérifie les permissions
48export function authorize(...required: Permission[]) {
49 return (req: Request, res: Response, next: NextFunction) => {
50 const userPerms = ROLE_PERMISSIONS[req.user.role] ?? [];
51 const hasAll = required.every((p) => userPerms.includes(p));
52 if (!hasAll) {
53 return res.status(403).json({ error: "Permissions insuffisantes" });
54 }
55 next();
56 };
57}
58
59// Utilisation dans les routes
60router.post(
61 "/tutorials",
62 authenticate,
63 authorize("tutorial:create"),
64 createTutorialController
65);
66
67router.delete(
68 "/tutorials/:id",
69 authenticate,
70 authorize("tutorial:delete"),
71 deleteTutorialController
72);