Plan du site  
pixel
pixel

Articles - Étudiants SUPINFO

NodeJS - ExpressJS : L'authentification avec PassportJS

Par Laurent PHILIBERT Publié le 14/09/2016 à 17:38:38 Noter cet article:
(0 votes)
Avis favorable du comité de lecture

Préambule

Dans cet article, vous apprendrez à utiliser et comprendre une bibliothèque qui vous permettra de vous authentifier sur votre application NodeJS générée à partir du framework ExpressJS. Bien entendu, il existe des dizaines de façons de créer un module d’authentification grâce aux NPM et à ExpressJS. Cependant, ici, nous traiterons uniquement la bibliothèque PassportJS.

Introduction

Revenons un peu aux bases… NodeJS est un langage web, le Javascript, orienté serveur, permettant d’améliorer les expériences utilisateurs en proposant des applications rapides et puissantes. Cela s’explique par le fait que ce langage est basé sur les évènements.

Le framework ExpressJS, de son côté, est le plus utilisé et le plus populaire. Il permet une utilisation simple et rapide de Node Js ainsi qu’un système de routes et vues plus simple à gérer. Par ailleurs, le moteur de templates sur Express JS, Jade, permet d’accélérer le développement des vues.

Dans cet article, nous utiliserons une base de données orientée documents, comme vous vous en doutez, nous utiliserons MongoDB. Il faut savoir qu’elle permet de stocker de façon plus souple des données qui ne sont pas homogènes. Elle permet également de gérer de grandes quantités de données en facilitant l’extension, on parle alors de scaling.

PassportJS

PassportJS est un node package module permettant de gérer l’authentification en partant de la création de compte jusqu’à la connexion. Il est préconfiguré pour travailler avec Mongo DB qui lui permet d’insérer les caractéristiques de l’utilisateur (email – mot de passe en hash) dans la base de donnée NoSQL.

De plus, il permet également la connexion à ce compte tout en allant sélectionner et vérifier l’existence de l’utilisateur dans la base de données Mongo DB.

Comment l'utiliser ?

Pour des raisons pratiques, je ne détaillerai pas les étapes d’installation des technologies que nous utiliserons (NodeJS, ExpressJS et MongoDB), je vous invite à aller voir des tutoriels en relation avec ces dernières.

Génération du projet

Pour commencer, vous devez générer un projet depuis ExpressJS. Pour cela :

		    	express mon_projet
		    

Installation des packages

Une fois que cela est fait, allez dans le dossier du projet et lancez l’installation de ces nodes packages :

		    	npm install --save cookie-parser body-parser express-session mongoose passport passport-local passport-local-mongoose 
		    

Modèle Account.js

Ensuite, ajoutez le fichier account.js dans un dossier appelé « models » :

				var passport = require('passport');

				var mongoose = require('mongoose');
				var Schema = mongoose.Schema;
				var passportLocalMongoose = require('passport-local-mongoose');

				var Account = new Schema({
				    username: String,
				    password: String
				});

				Account.plugin(passportLocalMongoose);

				module.exports = mongoose.model('Account', Account);
			

Configuration de app.js

Rajoutez ces lignes au fichier app.js qui est dans la racine de votre projet :

				var routes = require('./routes/index');
				app.use('/', routes);

				app.use(session({
				  cookieName: 'session',
				  secret: 'keyboard cat',
				  resave: false,
				  saveUninitialized: false
				}));

				app.use(passport.initialize());
				app.use(passport.session());
			

De plus, ajoutez les lignes qui permettent de faire la configuration de PassportJS :

				var Account = require('./models/account');
				passport.use(new LocalStrategy(Account.authenticate()));

				passport.serializeUser(Account.serializeUser());
				passport.deserializeUser(Account.deserializeUser());
			

Le routing

Pour le routing, vous devrez créer un dossier « routes » (s’il n’existe pas déjà) et y créer un fichier index.js :

				var express = require('express');
				var passport = require('passport'); 
				var Account = require('../models/account');

				var router = express.Router();

				router.get('/', function (req, res) {
				  res.render('index', { user : req.user });
				});

				router.get('/register', function(req, res) {
				  if ( req.session.passport.user != null ) {
				    res.redirect('/');
				  } else {
				    res.render('register', {
				      title : 'Sign-up'
				    });
				  }
				});

				router.post('/register', function(req, res, next) {
				  Account.register(new Account({ username : req.body.username }), req.body.password, function(err, account) {
				    if (err) {
				      return res.render('register', { error : err.message });
				    }

				    passport.authenticate('local')(req, res, function () {
				      req.session.save(function (err) {
				        if (err) {
				          return next(err);
				        }
				        res.redirect('/');
				      });
				    });
				  });
				});

				router.get('/login', function(req, res) {
				  if ( req.session.passport.user != null ) {
				    res.redirect('/');
				  } else {
				    res.render('login', {
				      user : req.user,
				      title : 'Sign-in',
				      subTitle : 'Come back please !'
				    });
				  }
				});

				router.post('/login', passport.authenticate('local'), function(req, res) {
				  if ( req.session.passport.user != null ) {
				    res.redirect('/');
				  } else {
				    res.redirect('/register');
				  }
				});

				router.get('/logout', function(req, res) {
				  if ( req.session.passport.user != null ) {
				    req.logout();
				    res.redirect('/');
				  }
				  else {
				    res.redirect('/')
				  }
				});


				module.exports = router;
			

Expliquons un peu chaque route :

				router.get('/', function (req, res) {
				  res.render('index', { user : req.user });
				});
			

Pour cette première route, quand l’utilisateur appellera l’URI « / », nous le renverrons à la vue d’index avec les paramètres de l’utilisateur si celui-ci existe.

				router.get('/register', function(req, res) {
				  if ( req.session.passport.user != null ) {
				    res.redirect('/');
				  } else {
				    req.logout();
				    res.render('register', {
				      title : 'Sign-up'
				    });
				  }
				});
			

Pour cette deuxième route, nous décidons de ce que l’utilisateur va récupérer quand il appelle l’URI « /register », si une session passport existe, nous le redirigeons vers l’index, sinon nous le renvoyons sur la vue de création de compte : register / sign-up.

				router.post('/register', function(req, res, next) {
				  Account.register(new Account({ username : req.body.username }), req.body.password, function(err, account) {
				    if (err) {
				      return res.render('register', { error : err.message });
				    }

				    passport.authenticate('local')(req, res, function () {
				      req.session.save(function (err) {
				        if (err) {
				          return next(err);
				        }
				        res.redirect('/');
				      });
				    });
				  });
				});
			

Pour cette troisième route, nous allons enregistrer ce que l’utilisateur aura rentré dans la vue de création de compte depuis l’URI « /register ». Vous pouvez remarquer que nous appelons un nouvel objet « Account » afin de rentrer en paramètre les données que l’utilisateur aura entré dans le formulaire. S’il y a une erreur, nous le renvoyons vers la vue de création de compte avec un message d’erreur. Sinon, nous créons son nouveau compte et nous l’authentifions en lui créant une session.

				router.get('/login', function(req, res) {
				  if ( req.session.passport.user != null ) {
				    res.redirect('/');
				  } else {
				    res.render('login', {
				      user : req.user,
				      title : 'Sign-in',
				      subTitle : 'Come back please !'
				    });
				  }
				});
			

Pour cette quatrième route, nous réagissons lorsque l’utilisateur appelle l’URI « /login ». Si celui-ci a une session valide, nous le renvoyons vers l’index de l’application en étant authentifié, sinon nous le renvoyons vers la vue d’authentification, de connexion.

				router.post('/login', passport.authenticate('local'), function(req, res) {
				  if ( req.session.passport.user != null ) {
				    res.redirect('/');
				  } else {
				    res.redirect('/register');
				  }
				});
			

Pour cette cinquième route, nous souhaitons authentifier l’utilisateur lorsque celui-ci possède déjà un compte. Nous vérifions donc le compte grâce à Passport et si celui-ci nous renvoie un compte avec une session nous le renvoyons sur l’index des utilisateurs connectés sinon nous l’invitons à créer un compte depuis l’URI « /register ».

				router.get('/logout', function(req, res) {
				  if ( req.session.passport.user != null ) {
				    req.logout();
				    res.redirect('/');
				  }
				  else {
				    res.redirect('/')
				  }
				});
			

Pour cette sixième et dernière route, nous vérifions qu’une session est belle et bien active, si c’est le cas, nous détruisons la session avant de rediriger l’utilisateur sur la page d’accueil, sinon nous le redirigeons sur la page d’accueil directement.

Une fois que ces routes sont écrites, nous n’avons plus qu’à créer les vues correspondantes...

Les vues

Etant donné que nous avons généré le projet avec ExpressJS, nous utiliserons alors le moteur de template par défaut qui est Jade. Je vous invite à vous renseigner sur celui-ci si vous souhaitez avoir de plus amples informations à propos de cette technologie.

Nous allons donc créer 3 vues. Nous aurons donc la vue d’index, la vue d’inscription et la vue de connexion, le tout englobé par un layout.

Le layout :

				doctype html
				html
				    head
				        title= 'Mon Super Projet'
				        meta(name='viewport', content='width=device-width, initial-scale=1.0')
				        
				        link(rel='stylesheet', href='/stylesheets/style.css')
				        link(rel='stylesheet', href='/stylesheets/bootstrap-social.css')
				        link(href='https://fonts.googleapis.com/icon?family=Material+Icons', rel='stylesheet')
				        link(href='/stylesheets/materialize.css' type='text/css' rel='stylesheet' media='programlisting,projection')
				        link(rel='stylesheet', href='/stylesheets/font-awesome.min.css')
				        link(rel='shortcut icon', type='image/x-icon', href='/images/favicon.ico')
				    body
				        include navbar
				        .container
				            if (error > 0)
				            br
				            h4.error-msg= error
				            br
				        block content
				        include footer
				        script(src='/javascripts/materialize.js')
				        script(src='/javascripts/ front.js')
			

La vue d'index :

				extends layout
				block content
				    if (!user)
				        #index-banner.section.no-pad-bot
				          .container
				          h3.center.blue-text Join us ! 
				          a(href='/login) Sign-in !
				          a(href='/register) Sign-up !
				    if (user)
				        #index-banner.section.no-pad-bot
				          .container
				          h3.center.blue-text Welcome back #{user.username}
				          a(href='/logout) Sign-out !    		
			

La vue d’inscription :

				extends layout
				block content
				   .container
				      .content_div_class
				         h1 #{title}
				         br
				         form(role='form', action="/register",method="post", style='max-width: 300px;')
				            .form-group
				               input.form-control(type='text', name="username", placeholder='mail address')
				            .form-group
				               input.form-control(type='password', name="password", placeholder='password')
				            .btn-group
				               button.blue.btn.btn-default.waves-effect.waves-light(type='submit') register
		    

La vue de connexion :

				extends layout
				block content

				   .container
				      .content_div_class
				         h1 #{title}
				         p.lead #{subTitle}
				         br
				         form(role='form', action="/login",method="post", style='max-width: 300px;')
				            .form-group
				               input.form-control(type='text', name="username", placeholder='mail address')
				            .form-group
				               input.form-control(type='password', name="password", placeholder='password')
				            .btn-group
				               button.blue.btn.btn-default.waves-effect.waves-light(type='submit') login
			

Conclusion

Il peut s’avérer très pratique d’utiliser PassportJS pour gérer ses authentifications lorsqu’on débute avec NodeJS. De plus, nous verrons par la suite (dans d’autres articles) comment utiliser PassportJS pour pouvoir s’inscrire et/ou se connecter à une application web depuis des applications tierces telles que Google+ ou Facebook.

A propos de SUPINFO | Contacts & adresses | Enseigner à SUPINFO | Presse | Conditions d'utilisation & Copyright | Respect de la vie privée | Investir
Logo de la société Cisco, partenaire pédagogique de SUPINFO, la Grande École de l'informatique, du numérique et du management Logo de la société IBM, partenaire pédagogique de SUPINFO, la Grande École de l'informatique, du numérique et du management Logo de la société Sun-Oracle, partenaire pédagogique de SUPINFO, la Grande École de l'informatique, du numérique et du management Logo de la société Apple, partenaire pédagogique de SUPINFO, la Grande École de l'informatique, du numérique et du management Logo de la société Sybase, partenaire pédagogique de SUPINFO, la Grande École de l'informatique, du numérique et du management Logo de la société Novell, partenaire pédagogique de SUPINFO, la Grande École de l'informatique, du numérique et du management Logo de la société Intel, partenaire pédagogique de SUPINFO, la Grande École de l'informatique, du numérique et du management Logo de la société Accenture, partenaire pédagogique de SUPINFO, la Grande École de l'informatique, du numérique et du management Logo de la société SAP, partenaire pédagogique de SUPINFO, la Grande École de l'informatique, du numérique et du management Logo de la société Prometric, partenaire pédagogique de SUPINFO, la Grande École de l'informatique, du numérique et du management Logo de la société Toeic, partenaire pédagogique de SUPINFO, la Grande École de l'informatique, du numérique et du management Logo du IT Academy Program par Microsoft, partenaire pédagogique de SUPINFO, la Grande École de l'informatique, du numérique et du management

SUPINFO International University
Ecole d'Informatique - IT School
École Supérieure d'Informatique de Paris, leader en France
La Grande Ecole de l'informatique, du numérique et du management
Fondée en 1965, reconnue par l'État. Titre Bac+5 certifié au niveau I.
SUPINFO International University is globally operated by EDUCINVEST Belgium - Avenue Louise, 534 - 1050 Brussels