• 10 hours
  • Medium

Free online content available in this course.

course.header.alt.is_video

course.header.alt.is_certifying

Got it!

Last updated on 11/26/21

Configurez le middleware d'authentification

Log in or subscribe for free to enjoy all this course has to offer!

Implémentez le middleware d'authentification

Nous allons à présent créer le middleware qui protégera les routes sélectionnées et vérifiera que l'utilisateur est authentifié avant d'autoriser l'envoi de ses requêtes.

Créez un dossier middleware et un fichier auth.js à l'intérieur :

const jwt = require('jsonwebtoken');
module.exports = (req, res, next) => {
try {
const token = req.headers.authorization.split(' ')[1];
const decodedToken = jwt.verify(token, 'RANDOM_TOKEN_SECRET');
const userId = decodedToken.userId;
if (req.body.userId && req.body.userId !== userId) {
throw 'Invalid user ID';
} else {
next();
}
} catch {
res.status(401).json({
error: new Error('Invalid request!')
});
}
};

Dans ce middleware :

  • étant donné que de nombreux problèmes peuvent se produire, nous insérons tout à l'intérieur d'un bloc try...catch ;

  • nous extrayons le token du header Authorization de la requête entrante. N'oubliez pas qu'il contiendra également le mot-clé Bearer . Nous utilisons donc la fonction split pour récupérer tout après l'espace dans le header. Les erreurs générées ici s'afficheront dans le bloc catch ;

  • nous utilisons ensuite la fonction verify pour décoder notre token. Si celui-ci n'est pas valide, une erreur sera générée ;

  • nous extrayons l'ID utilisateur de notre token ;

  • si la demande contient un ID utilisateur, nous le comparons à celui extrait du token. S'ils sont différents, nous générons une erreur ;

  • dans le cas contraire, tout fonctionne, et notre utilisateur est authentifié. Nous passons l'exécution à l'aide de la fonction next() .

Maintenant, nous devons appliquer ce middleware à nos routes stuff , qui sont celles à protéger. Dans notre routeur stuff , nous importons notre middleware et le passons comme argument aux routes à protéger :

const express = require('express');
const router = express.Router();
const auth = require('../middleware/auth');
const stuffCtrl = require('../controllers/stuff');
router.get('/', auth, stuffCtrl.getAllStuff);
router.post('/', auth, stuffCtrl.createThing);
router.get('/:id', auth, stuffCtrl.getOneThing);
router.put('/:id', auth, stuffCtrl.modifyThing);
router.delete('/:id', auth, stuffCtrl.deleteThing);
module.exports = router;

Désormais, à partir du front-end, vous devriez être capable de vous connecter et d'utiliser normalement l'application. Pour vérifier que les requêtes non autorisées ne fonctionnent pas, vous pouvez utiliser une application (telle que Postman) pour passer une demande sans en-tête Authorization . L'API refusera l'accès et renverra une réponse 401.

Félicitations ! Votre API implémente à présent l'authentification par token et est correctement sécurisé. mais est-ce vraiment le cas ?

À vous de jouer ! Trouvez la faille d'autorisation

Je vous présente ici le challenge qui vous attend, à savoir trouver la faille d'autorisation dans notre API.

Il se trouve que nous avons une vulnérabilité de sécurité dans notre API. L'une de nos routes permet potentiellement à la mauvaise personne de réussir à effectuer une requête. Voyez-vous où le problème se trouve ? Avez-vous une idée de la manière dont on pourrait le résoudre ?

Voici votre mission :

  1. Trouver la route qui a ce problème : quelle route comporte cette faille de sécurité ? 

  2.  Réparer cette vulnérabilité et trouver comment résoudre ce problème de sécurité. 

N'hésitez pas à réécouter le challenge, qui vient avec un indice pour vous orienter vers la solution ! ;) . Et si vraiment vous n'y arrivez pas, ne vous inquiétez pas, je vous explique tout de suite ci-dessous le détail de la solution.

Résolvons le problème ensemble

Regardons ensemble comment procéder pour réussir ce challenge !

Eh oui, la route qui comporte une faille de sécurité est bien la route DELETE. Pourquoi ? Parce que notre application front-end ne nous envoie pas d'ID utilisateur quand elle demande la suppression d'un Thing, donc actuellement nous ne sommes pas en mesure de vérifier si l'utilisateur qui effectue la requête est bien le propriétaire du Thing qu'il essaie de supprimer. En théorie, donc, tout utilisateur ayant un token valable pourrait supprimer le Thing de N'IMPORTE QUI. Une sacrée faille !

Donc comment la réparer ? Eh bien, vu que nous n'avons pas la main sur l'application front-end, il nous faut un moyen de comparer l'ID utilisateur du token avec le champ userId du Thing que nous avons récupéré de la base de données. Le défi ici est que nous n'avons actuellement pas accès à l'ID utilisateur extrait du token dans notre contrôleur DELETE. Il y a, cependant, une solution simple :

  • Dans notre middleware d'authentification, nous ajoutons un objet  auth  à l'objet de requête qui contient le  userId  extrait du token :

req.auth = { userId };
  • Dans notre contrôleur DELETE, d'abord nous récupérons le Thing en base de données, ensuite nous vérifions qu'il appartient bien à l'utilisateur qui effectue la requête – si c'est le cas, nous supprimons le Thing ; sinon, nous retournons une erreur :

exports.deleteThing = (req, res, next) => {
Thing.findOne({ _id: req.params.id }).then(
(thing) => {
if (!thing) {
res.status(404).json({
error: new Error('No such Thing!')
});
}
if (thing.userId !== req.auth.userId) {
res.status(400).json({
error: new Error('Unauthorized request!')
});
}
Thing.deleteOne({ _id: req.params.id }).then(
() => {
res.status(200).json({
message: 'Deleted!'
});
}
).catch(
(error) => {
res.status(400).json({
error: error
});
}
);
}
)
};

Ainsi, seul le propriétaire d'un Thing peut le supprimer !

En résumé

  • La méthode  verify()  du package jsonwebtoken permet de vérifier la validité d'un token (sur une requête entrante, par exemple).

  • Ajoutez bien votre middleware d'authentification dans le bon ordre sur les bonnes routes.

  • Attention aux failles de sécurité !

Qu'avez-vous appris dans cette partie du cours ?

  • Vous avez ajouté un modèle de données User afin de stocker les informations utilisateur dans votre base de données.

  • Vous avez implémenté le cryptage de mot de passe sécurisé afin de stocker en toute sécurité les mots de passe utilisateur.

  • Vous avez créé et envoyé des tokens au front-end pour authentifier les requêtes.

  • Vous avez ajouté le middleware d'authentification pour sécuriser les routes dans votre API. De cette façon, seules les requêtes authentifiées seront gérées.

Dans la dernière partie de ce cours, vous en apprendrez plus sur la gestion des fichiers :

  • comment capturer les fichiers provenant du front-end ;

  • comment les enregistrer sur votre serveur ;

  • comment les supprimer lorsqu'ils ne sont plus nécessaires.

Example of certificate of achievement
Example of certificate of achievement