Votre PassPort ! (Partie 2)

PassPort

Deuxième tour : l’idée est d’intégrer une deux autres stratégies dans le premier projet.

GitHub

Actions

Je ne sais pas si c’est le plus simple mais c’est celui qui m’a paru le plus évident pour commencer … Alors dans l’ordre :

  • Création d’une application dans GitHub (ici)
  • Mise à jour de la configuration pour intégration des clés,
  • Installation du package : npm install passport-github2 (comme, je suis en Npm 5 plus besoin du –save),
  • Intégration de la nouvelle stratégie (pris sur l’exemple …)
  • Ajout des deux routes,
  • Test manuelle : semble bien fonctionner. Le souci semble être plus dans le lien avec l’appli …

Bon par contre, j’ai eu quelques petites contrariétés, mais qui sont dus à des mauvaises manipulations de ma part :

  • Récupération d’une email: l’exemple n’est pas bon au niveau du scope. Il faut mettre la demande scope dans la route mais également dans la stratégie. Dans ce cas, Passport va faire un appel de plus pour récupérer l’adresse mail
  • Flash Message : c’est pour bien écrit pour que les flash-messages fonctionnent, il faut mettre failureFlash : true en paramètre …

Bilan

Pour le coup, c’était simple. Les problèmes que j’ai rencontré étaient clairement de ma responsabilité donc je vois bien l’intérêt.

Un petit Jeton

Préambule

Il existe des stratégie qui permette de gérer une identification avec un jeton JWT mais je n’ai pas trouvé de solution qui s’associait avec ce que j’avais déjà implémenté. Donc, je suis parti sur une solution “simple” reprenant différente lecture et formation déjà réalisée

Actions

J’ai défini une nouvelle route de login qui utilise la stratégie locale mais pas en tant que MiddleWare mais en tant que service appelé. Je passe en paramètre req & res et effectue un retour standard avec génération d’un jeton JWT via la librairie jsonwetoken :

router.post('/login',  (req, res, next) => {
    // Appel de passport
    passport.authenticate('local-login', { session : false }
         , (err, data, message) => {
                // Si j'ai une erreur dans le traitement du côté de passport
                if(err) { return res.status(500).json({ success: false, message: err.message }); }

                // Si j'ai pas de data = user
                if(!data) { return res.status(401).json( { success: false, message : message }); }

                // J'ai bien un user : je lui retourne un token
                const info = {
                    success: true
                    , message: 'Authenticated'
                    , data: {
                        // Génération du token avec la librairie jsonwebtoken
                        token : jwt.sign({ id: data._id }, config.app.secret, { expiresIn: '24h'} )
                        , username: data.username
                    }
                };
                return res.status(200).json(info);
        })(req, res); // Authenticate
    });

Ensuite, j’ai crée un nouveau MiddleWare qui vérifie que le jeton est valide :

router.use((req, res, next) => {
    // Récupération du token
    const token = req.headers['authorization']; 
    // !token ?
    if (!token) { res.json({ success: false, message: 'No token provided' }); return; } 

    // Le token ayant été "crée" par jwt, on lui demande de recommencer le travail :)
    jwt.verify(token, config.app.secret, (err, decoded) => {
        if (err) { res.json({ success: false, message: 'Token invalid: ' + err }); return ;}

        // Ajout de ce qui a été décode (user._id) pour utilisation dans la suite du process
        req.decoded = decoded; 
        // Passage à la méthode suivante
        next(); 
    });
});

Finalement, j’ai une route située après ce MiddleWare qui me permet de répondre à la requête de l’utilisateur :

router.get('/ping', (req, res, next) => {
    //res.send(req.decoded);
    // Recherche
    Account.findOne({ _id: req.decoded.id }).select('username email').exec((err, user) => {
        // err ?
        if (err) { res.json({ success: false, message: err }); return; } 

        // Check if user was found in database
        if (!user) {
            res.json({ success: false, message: 'User not found' }); 
        } else {
            res.json({ success: true, user: user }); 
        }
    }); 
});

Test

Merci Postman !

Bilan

Après une 2ème journée, je comprends mieux l’intérêt : ca fait pas tout mais ça aide bien ! Maintenant, il faudrait voir comment partager une identification entre GitHub, Local & Jwt mais ça ce sera pour un autre demain !

Liens