Partage
  • Partager sur Facebook
  • Partager sur Twitter

Sécurisation des pages - expressJS

    4 janvier 2021 à 22:14:15

    Bonjour,

    J'essaie de développer une application ou toutes les pages seraient sécurisés; il faudrait être connecté pour pouvoir accéder aux différentes pages. 

    Apparemment ça marche mais une fois connecté, je vous rediriger l'utilisateur sur une autre page, je reçois une erreur disant qu'un token est requis (jwt). 

    Cela fait plusieurs jours que j'essaie de trouver une solution mais sans résultat. 

    Pouvez-vous m'aider ?

    Voici mon code

    routes/users.js

    var express = require('express');
    var router = express.Router();
    
    const userController = require('../controllers/userController');
    
    router.get('/login', userController.login_get);
    router.get('/signup', userController.signup_get);
    
    router.post('/signup', userController.signup_post);
    router.post('/login', userController.login_post);
    
    module.exports = router;
    

    routes/machines.js (toutes ces routes sont préfixer par /machines)

    const express = require('express');
    const router = express.Router();
    
    const auth = require('../middleware/auth');
    const machineController = require('../controllers/machineController');
    
    
    router.post('/create', auth, machineController.machine_create_post);
    router.get('/create', auth, machineController.machine_create_get);
    router.post('/:id/update', auth, machineController.machine_update_post);
    router.get('/:id/update', auth, machineController.machine_update_get);
    router.post('/:id/delete', auth, machineController.machine_delete);
    router.get('/:id', auth, machineController.machine_detail);
    router.get('/', auth, machineController.machine_list);
    
    
    module.exports = router;


    controllers/userController.js

    var bcrypt = require('bcrypt');
    const User = require('../models/User');
    const jwt = require('jsonwebtoken');
    
    exports.signup_get = async function (req, res, next) {
        res.render('user/signup');
    }
    
    exports.signup_post = async function (req, res, next) {
        bcrypt.hash(req.body.password, 10)
            .then(hash => {
                const user = new User({
                    firstname: req.body.firstname,
                    surname: req.body.surname,
                    email: req.body.email,
                    password: hash
                });
    
                user.save()
                    .then(() => {
                        token = jwt.sign({ userId: user._id }, 'RANDOM_TOKEN_SECRET', { expiresIn: '24h' });
                        console.log('token : ' + token);
                        //res.json({ userId: user._id, token });
    
                        res.set('x-token', token);
                        res.redirect('/machines');
                    })
                    .catch((error) => {
                        next(error);
                    });
            })
            .catch((error) => {
                next(error);
            })
    }
    
    exports.login_get = async function (req, res, next) {
        res.render('user/login');
    }
    
    exports.login_post = async function (req, res, next) {
        User.findOne({ email: req.body.email })
            .then((user) => {
                if(!user)
                    return res.render('user/login', { message: "Email ou mot de passe incorrect." });
    
                bcrypt.compare(req.body.password, user.password)
                    .then((valid) => {
                        if(!valid)
                            return res.redirect('/login', { message: "Email ou mot de passe incorrect." });
    
                      
                        const token = jwt.sign({ userId: user._id }, 'RANDOM_TOKEN_SECRET', { expiresIn: '24h' });
                        
                        console.log('token :' + token);
                        res.header('token', token);
                        res.status(200).redirect('/machines');
                    })
                    .catch((error) => {
                        next(error);
                    });
            })
            .catch((error) => {
                next(error);
            })
    }

    controllers/machineController.js

    const createError = require('http-errors');
    const { body, validationResult } = require('express-validator');
    const Machine = require('../models/Machine');
    const machineView = 'machine';
    
    //Display list of all Machine
    exports.machine_list = async function (req, res, next) {
        Machine.find()
        .then((machines) => {
            res.render(machineView + '/machine_list', { machines });
        })
        .catch((error) => {
            next(error);
        })
    }
    
    //Display detail page for a specific Machine
    exports.machine_detail = async function (req, res, next) {
        Machine.findOne({
            _id: req.params.id
        })
        .then((machine) => {
    
            if(machine === null)
                return next(createError(404, 'Aucune machine trouvée'));
    
            res.render(machineView + '/machine_detail', { machine });
        })
        .catch((error) => {
            next(error);
        })
    }
    
    //Display form for create a Machine 
    exports.machine_create_get = async function (req, res, next) {
        res.render(machineView + '/machine_form');
    }
    
    //Processing of adding a new machine to the database 
    exports.machine_create_post = [
        body('name', 'Le champ nom ne peut être vide').notEmpty(),
        body('price_minute', 'Le champ prix ne peut être vide').notEmpty(),
        body('price_minute', 'Le champ prix doit avoir une valeur numérique').isNumeric(),
    
        async function (req, res, next) {
    
            const errors = validationResult(req);
    
            if (!errors.isEmpty()) {
                return res.render(machineView + '/machine_form', {
                    machine: req.body,
                    errors: errors.array()
                });
            }
    
            const machine = new Machine({
                name: req.body.name,
                price_minute: req.body.price_minute
            });
    
            machine.save()
            .then(() => {
                res.redirect('/machines/');
            })
            .catch((error) => {
                next(error);
            });
        }
    ];
    
    //Display form for update a specific Machine
    exports.machine_update_get = async function (req, res, next) {
        Machine.findOne({
            _id: req.params.id
        })
        .then((machine) => {
            if(machine === null)
                return next(createError(404, 'Aucune machine trouvée'));
    
            res.render(machineView + '/machine_form', { machine });
        })
        .catch((error) => {
            next(error);
        });
    }
    
    //Processing of updating a new machine to the database
    exports.machine_update_post = [
        body('name', 'Le champ nom ne peut être vide').notEmpty(),
        body('price_minute', 'Le champ prix ne peut être vide').notEmpty(),
        body('price_minute', 'Le champ prix doit avoir une valeur numérique').isNumeric(),
    
        async function (req, res, next) {
    
            const errors = validationResult(req);
    
            if (!errors.isEmpty()) {
                return res.render(machineView + '/machine_form', {
                    machine: req.body,
                    errors: errors.array()
                });
            }
     
            const machine = new Machine({
                _id: req.params.id,
                name: req.body.name,
                price_minute: req.body.price_minute
            });
    
            Machine.updateOne({ _id: req.params.id }, machine)
            .then(() => {
                res.redirect('/machines');
            })
            .catch((error) => {
                next(error);
            });
        }
    ];
    
    //Deleting a specific machine
    exports.machine_delete = async function (req, res, next) {
        Machine.deleteOne({ _id: req.params.id })
        .then(() => {
            res.redirect('/machines');
        })
        .catch((error) => {
            next(error);
        });
    }
    

    middlewares/auth.js

    const jwt = require('jsonwebtoken');
    
    module.exports =  function(req, res, next) {
        try {
            console.log('auth method');
            const authHeader = req.header['token'];
            const token = authHeader && authHeader.split(' ')[1];
            console.log('token : ' + token);
            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(error) {
            next(error);
        }
    }





    -
    Edité par IAlm 4 janvier 2021 à 22:23:25

    • Partager sur Facebook
    • Partager sur Twitter
      5 janvier 2021 à 9:33:38

      Salut,

      Ligne 56 de ton fichier userController.js : L'en-tête devrait être nommé Authorization (plutôt que token) et le token devrait être de type Bearer :

      res.header('Authorization', `Bearer ${token}`);

      Ensuite, tu dois de démerdé coté client pour que toutes les requêtes server soit réalisées en communiquant ce même en-tête avec la même valeur de sorte à pouvoir décrypter par la suite le token coté serveur et donc vérifier que l'utilisateur est bien connecter. (Ou bien tu te sert d'un cookie pour le retransmettre, mais là tu as l'air d'être partie sur la méthode avec les en-têtes...)

      Tu modifies donc ta ligne 6 du fichier auth.js de la sorte :

      const authHeader = req.header['Authorization'];

      -
      Edité par BrainError 5 janvier 2021 à 10:10:26

      • Partager sur Facebook
      • Partager sur Twitter
        6 janvier 2021 à 13:09:49

        Merci pour ton aide mais ça ne marche toujours pas. Il m'affiche toujours le même message.

        -
        Edité par IAlm 6 janvier 2021 à 13:10:37

        • Partager sur Facebook
        • Partager sur Twitter
          6 janvier 2021 à 13:26:22

          Salut,

          Ligne 8 de middlewares/auth.js, ton log renvoi quoi ? Il renvoi bien le token ?

          • Partager sur Facebook
          • Partager sur Twitter
            6 janvier 2021 à 21:39:44

            il me renvoi undefined.

            Par contre, le log ligne 55 dans userController me renvoi le token.

            Je ne comprends pas pourquoi il ne reçoit pas le token.

            -
            Edité par IAlm 9 janvier 2021 à 16:31:46

            • Partager sur Facebook
            • Partager sur Twitter

            Sécurisation des pages - expressJS

            × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
            × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
            • Editeur
            • Markdown