Utilisez JWT Tokens pour sécuriser votre application NestJS !
Découvrez comment sécuriser votre application NestJS avec JWT grâce à ce guide détaillé qui vous accompagnera pas à pas dans l'implémentation de ce système d’authentification ! 🚀
Par Maxime Blampain
Introduction
Dans le paysage numérique, la transmission et la gestion sécurisées des données sont primordiales. En tant que colonne vertébrale des applications web modernes, les API (Application Programming Interfaces) facilitent la communication fluide entre divers composants logiciels, permettant l’échange d’informations cruciales. Cependant, cette commodité comporte des risques de sécurité inhérents, notamment en ce qui concerne l’accès non autorisé à des endpoints sensibles. C’est là que le JSON Web Token (JWT) semble être une bonne option. Nous allons l’utiliser dans une application NestJS.
NestJS
NestJS est un framework permettant de développer des applications Node.js efficaces et scalables. Il utilise JavaScript de manière progressive et prend en charge TypeScript nativement. — Doc officielle NestJS
NestJS propose une architecture prête à l’emploi qui permet aux développeurs et aux équipes de créer des applications hautement testables, évolutives, faiblement couplées et facilement maintenables. Cette architecture est basée sur une structure en trois couches (Contrôleur, Services, Accès aux données), mais il existe de nombreuses manières de construire une application NestJS.
L’un des aspects fondamentaux de NestJS est l’injection de dépendances, un modèle de conception qui permet de créer et de gérer des objets au sein d’un environnement applicatif. Dans NestJS, l’injection de dépendances est utilisée pour fournir des instances de services à d’autres composants de l’application.
Si vous souhaitez en savoir plus sur NestJS, je vous invite à consulter leur site web.
JWT (Json Web Token)
JWT encapsule les donnés utilisateur sous format JSON, garantissant leur intégrité et leur authenticité tout au long de leur cycle de vie. Ces jetons offrent une solution sans état, qui améliore la scalabilité et simplifie l’implémentation. Avec JWT, les développeurs peuvent authentifier les utilisateurs, gérer l’accès aux ressources et établir la confiance dans les interactions numériques.
Une fois le token JWT déchiffré, le JSON ressemble à ça:
{"subject":"",// Email / ID du propriétaire du token, c’est l’identifiant principal"iat":42424242,// Date d’émission du token (Issued At)"exp":42428242,// Date d’expiration du token// Ensuite, vous pouvez ajouter ce que vous souhaitez"aud":"localhost",// Destination où le token est supposé être utilisé"iss":"localhost",// L'entité qui a créé le token"name":"John Doe","role":"user"// ...}
Qui suis-je ?
Ravi de vous rencontrer ! Je suis Maxime, ingénieur logiciel chez Vaduo Consulting. Vaduo est une ESN conviviale basée à Lille. Son système collaboratif et bienveillant permet à chacun de s’exprimer et d’être écouté afin d’aider l’entreprise à évoluer. Vaduo accompagne ses clients locaux dans leurs problématiques techniques et agiles.
Sa mission est de remettre l’humain au cœur de la technologie, avec un véritable intérêt pour le bien-être, l’expertise et le développement de ses employés, ainsi qu’une relation saine avec ses partenaires.
Commençons !
Dans cet article, nous allons suivre une approche étape par étape pour construire un projet NestJSsécurisé en utilisant JWT. Bien entendu, pour réaliser ce projet, vous aurez besoin de Node.js et de votre IDE favori. Le dépôt GitHub associé à ce guide est disponible ici si vous souhaitez consulter directement le code : GitHub
Installation et configuration du projet
Installation de NestJS et des dépendances
Installer la CLI NestJS et créer un projet :
npm install -g @nestjs/cli
nest new nest-jwt
Accéder au dossier du projet et installer les packages nécessaires :
cd nest-jwt
npm install @nestjs/jwt @nestjs/config
Maintenant, que JwtModule est importé dans notre AuthModule, on peut désormais injecter JwtService ainsi que la config JWT dans notre AuthService
import { Inject, Injectable } from'@nestjs/common';
import { JwtService } from'@nestjs/jwt';
import { ConfigType } from'@nestjs/config';
import { randomUUID } from'node:crypto';
import jwtConfig from'./jwt.config';
@Injectable()
exportclassAuthService {
publicconstructor(privatereadonlyjwtService: JwtService,
@Inject(jwtConfig.KEY)
privatereadonlyjwtConfiguration: ConfigType<typeof jwtConfig>,
) {}
publicasynclogin() {
// return a fake jwt token as long as this app is a templatereturnthis.jwtService.signAsync(
{
sub: randomUUID(),
email: 'my-email@example.com',
},
{
audience: this.jwtConfiguration.audience,
issuer: this.jwtConfiguration.issuer,
secret: this.jwtConfiguration.secret,
expiresIn: this.jwtConfiguration.accessTokenTtl,
},
);
}
}
Pour vérifier que tout fonctionne comme il faut, vous pouvez lancer votre application avec npm start . Vous pouvez maintenant tester votre endpoint API avec des outils tels que Postman, Bruno ou encore Insomnia.
Implémentation d’un Guard pour sécuriser des endpoints
Les gardes ont une responsabilité unique. Elles déterminent si une requête donnée est traitée par le gestionnaire de route ou non, en fonction de certaines conditions (comme les permissions, les rôles, les ACL, etc.) présentes au moment de l'exécution. — Doc officielle NestJS
Si vous souhaitez en apprendre plus sur les guards, un article est déjà disponible sur le blog juste ici.
Le but de notre Guard est de vérifier si notre token est toujours valide. Si c’est le cas, on injecte le contenu de notre token dans l’objet request dans la propriété user.
Pour ce faire, il faut:
Générer le fichier qui contiendra nos décorateurs
nest g decorator auth/decorators/auth
Créer les décorateurs pour définir les routes publiques et protégées:
En ce qui concerne public.guard.ts, le code est assez explicite.
import { CanActivate, ExecutionContext, Injectable } from'@nestjs/common';
@Injectable()
exportclassPublicGuardimplementsCanActivate {
// Vu que le guard public laisse tout passer, on retourne toujours "true"publiccanActivate(context: ExecutionContext): boolean {
returntrue;
}
}
Le but de ce guard est simple, on regarde les metadata pour savoir si notre endpoint API est public ou non. Puis on appelle un guard ou l’autre selon cette information.
Si on essaye d’accéder à la route “/” on reçoit une 401 vu que cet endpoint est sécurisé et nécessite un token pour y accéder
Maintenant, on se connecte via la route “login”
Une fois le token récupéré, essayons à nouveau
Nous avons vu comment implémenter JWT pour sécuriser une application NestJS en utilisant des décorateurs, des Guards et des services d’authentification. Grâce à cette méthode, vous pouvez garantir que seuls les utilisateurs authentifiés peuvent accéder aux endpoints sécurisés. N’hésitez pas à modifier des parties du code pour correspondre à vos besoins.