37-4 Connexion et retour de jeton JWT
La dernière étape consiste à procéder à l'authentification.
Le principe est le suivant:
- Recevoir les informations de connexion via une requête HTTP
- Passer les informations à la couche service (ex.: AuthService)
- Récupérer l'utilisateur de la BD correspondant au courriel (si existe)
- Comparer la version hachée du mot de passe dans la BD avec la version hachée du mot de passe reçu
- Si le tout concorde, générer un jeton JWT
- Si le tout ne concorde pas, retourner une erreur d'authentification.
Créer l'action connexion du contrôleur auth
Dans le contrôleur d'authentification, on créera une action responsable de répondre via POST à /auth.
@ApiTags('auth')
@Controller('auth')
export class AuthController {
@Post()
async connexion(@Body() requeteConnexionDto: RequeteConnexionDto) {
}
}
Cela créera en effet un chemin associé au niveau de l'API.

Créer l'action connexion associée au niveau du service
@Injectable()
export class AuthService {
async connexion(requeteConnexionDto: RequeteConnexionDto) {
}
}
Ensuite, le contrôleur peut y faire appel.
export class AuthController {
constructor(private authService: AuthService) {}
@Post()
async connexion(@Body() requeteConnexionDto: RequeteConnexionDto) {
return this.authService.connexion(requeteConnexionDto);
}
}
Procéder à la connexion
- La première étape consiste à récupérer l'utilisateur de la base de données.
async connexion(requeteConnexionDto: RequeteConnexionDto) {
const utilisateur = // OH NON, CE BOUT DE CODE EST MANQUANT!
// Vous devrez trouver l'utilisateur par son courriel.
// N'ubliez pas de convertir le courriel reçu en `lowercase` pour faire la recherche.
}
- Vérifier si un utilisateur a été retourné
async connexion(requeteConnexionDto: RequeteConnexionDto) {
const utilisateur = // VOTRE CODE DE RÉCUPÉRATION
if(!utilisateur) {
throw new UnauthorizedException();
}
Bien qu'il est préférable d'utiliser le contrôleur pour retourner des codes d'erreur HTTP, comme nous avons quelques cas de figure à considérer ici, il demeure plus simple de les générer directement dans le service.
Il est déjà possible de faire un premier test Postman vers un utilisateur qui n'existe pas dans la BD. Par exemple.
POST http://localhost:3000/auth
{
"courriel": "NotFoundbenoit.tremblay@cegepdrummond.ca",
"password": "p@ssword"
}
Devrait retourner une erreur 401 Unauthorized.
- Comparer le mot de passe reçu avec celui dans la base de données. Pour vérifier le mot de passe de l'utilisateur, on peut comparer celui reçu avec celui dans la BD. Mais attention, il faut hasher le mot de passe reçu pour vérifier que la signature est la même que celle en BD.
bcryptoffre la fonctionnalitécomparepour cela.
async connexion(requeteConnexionDto: RequeteConnexionDto) {
const utilisateur = // VOTRE CODE DE RÉCUPÉRATION
if(!utilisateur) {
throw new UnauthorizedException();
}
const passwordMatch = // UTILISER bcrypt.compare POUR COMPARER LES MOTS DE PASSE
if(!passwordMatch){
throw new UnauthorizedException();
}
}
La librairie bcrypt expose une fonction compare qui permet de passer en premier argument un mot de passe en texte clair et en deuxième argument un mot de passe haché.
La fonction compare s'occupera premièrement de hacher le mot de passe reçu en texte clair, puis de comparer le hash par la suite.
Cette action est possible puisque le mot de passe haché dans la base de données contient les informations suivantes: le salt utilisé, le coût de l'algorithme (itérations) et le mot de passe haché.
- Retourner un jeton JWT signé
constructor(private jwtService: JwtService) {}
async connexion(requeteConnexionDto: RequeteConnexionDto) {
const utilisateur = // VOTRE CODE DE RÉCUPÉRATION
if(!utilisateur) {
throw new UnauthorizedException();
}
const passwordMatch = // VOTRE CODE
if(!passwordMatch){
throw new UnauthorizedException()
}
const access_token = this.jwtService.sign({
sub: utilisateur.id,
courriel: utilisateur.courriel,
nomUtilisateur: utilisateur.nomUtilisateur,
});
return { access_token };
}
jwtService.sign signe un jeton avec la clé secrète du fichier de configuration. Le jeton est au fonds un objet JSON, encodé par la suite en base64.
subpoursubject, soit l'identifiant de l'utilisateurcourriel: le courriel de l'utilisateurnomUtilisateur: le nom d'utilisateur
Test Postman
Il est maintenant temps d'essayer une requête de connexion!
POST http://localhost:3000/auth- body (sera possiblement différent dans votre cas selon votre user/pw)
{
"courriel": "benoit.tremblay@cegepdrummond.ca",
"password": "p@ssword"
}
Si tout se passe bien, vous devriez recevoir un jeton!
{
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOjMsImNvdXJyaWVsIjoiYmVub2l0LnRyZW1ibGF5QGNlZ2VwZHJ1bW1vbmQuY2EiLCJub21VdGlsaXNhdGV1ciI6ImJlbnRyZW1ibGF5IiwiaWF0IjoxNjk5NjI4NTMyLCJleHAiOjE2OTk2Mjg1MzJ9.aJ-t9Kpb8lKlAfcCR4E0kHfYzJv6Vpcggzvfkobalik"
}
Vous pouvez même utiliser le site jwt.io pour décoder le jeton et en voir le contenu:
