Fermer

avril 8, 2020

Authentification locale à l'aide de Passport dans Node.js


Une exigence courante lors de la création d'une application Web est d'implémenter un système de connexion, afin que les utilisateurs puissent s'authentifier avant d'accéder aux vues ou aux ressources protégées. Heureusement pour ceux qui créent des applications Node, il existe un middleware appelé Passport qui peut être déposé dans n'importe quelle application Web basée sur Express pour fournir des mécanismes d'authentification en seulement quelques commandes.

tutoriel, je vais vous montrer comment utiliser Passport pour implémenter l'authentification locale (c'est-à-dire la connexion avec un nom d'utilisateur et un mot de passe) avec un serveur principal MongoDB. Si vous cherchez à implémenter l'authentification via Facebook ou GitHub, veuillez vous référer à ce tutoriel .

Comme toujours, tout le code de cet article est disponible en téléchargement sur GitHub .

Prérequis

Pour suivre ce didacticiel, vous devez avoir installé Node et MongoDB sur votre machine.

Vous pouvez installer Node en vous dirigeant vers [1945901313]. ] la page de téléchargement officielle du nœud et en récupérant les binaires appropriés pour votre système. Alternativement, vous pouvez utiliser un gestionnaire de versions – un programme qui vous permet d'installer plusieurs versions de Node et de basculer entre elles à volonté. Si vous avez envie de suivre cette voie, veuillez consulter notre astuce, « Installer plusieurs versions de Node.js à l'aide de nvm ».

MongoDB est disponible en plusieurs éditions. Celui qui nous intéresse est l'édition communautaire de MongoDB.

La page d'accueil du projet contient une excellente documentation et je n'essaierai pas de la reproduire ici. Je vous propose plutôt des liens vers des instructions pour chacun des principaux systèmes d'exploitation:

Si vous utilisez une version de Linux non basée sur Ubuntu, vous pouvez consulter cette page pour obtenir des instructions d'installation pour autres distributions. MongoDB est également normalement disponible via les canaux logiciels officiels de Linux, mais parfois cela entraînera une version obsolète.

Remarque: Vous n'avez pas besoin d'entrer votre nom et votre adresse pour télécharger MongoDB. Si vous y êtes invité, vous pouvez normalement fermer la boîte de dialogue.

Si vous souhaitez un bref rappel sur l'utilisation de MongoDB, consultez notre guide du débutant, " Une introduction à MongoDB ".

Stratégies d'authentification: Session vs JWT

Avant de commencer, parlons brièvement des choix d'authentification.

De nombreux didacticiels en ligne aujourd'hui opteront pour l'authentification basée sur des jetons à l'aide de JSON Web Tokens (JWTs). Cette approche est probablement la plus simple et la plus populaire de nos jours. Il relègue une partie de la responsabilité d'authentification au client et lui fait signer un jeton qui est envoyé avec chaque demande, pour garder l'utilisateur authentifié.

L'authentification basée sur la session existe depuis plus longtemps. Cette méthode relègue le poids de l'authentification au serveur. Il utilise des cookies et voit l'application Node et la base de données fonctionner ensemble pour garder une trace de l'état d'authentification d'un utilisateur.

Dans ce tutoriel, nous allons utiliser l'authentification basée sur la session, qui est au cœur du passeport . stratégie locale

Les deux méthodes ont leurs avantages et leurs inconvénients. Si vous souhaitez en savoir plus sur la différence entre les deux, ce fil de débordement de pile peut être un bon point de départ.

Création du projet

Une fois que tous les logiciels prérequis sont définis , nous pouvons commencer.

Nous allons commencer par créer le dossier de notre application, puis accéder à ce dossier sur le terminal:

 mkdir AuthApp
cd AuthApp

Pour créer l'application de nœud, nous utiliserons la commande suivante:

 npm init

Vous serez invité à fournir des informations sur le package Node du nœud. Continuez à appuyer sur Retournez pour accepter la configuration par défaut (ou utilisez l'indicateur -y ).

Configuration d'Express

Maintenant, nous devons installer Express . Accédez au terminal et entrez cette commande:

 npm install express

Nous devons également installer le middleware body-parser qui est utilisé pour analyser le corps de la requête que Passport utilise pour authentifier l'utilisateur. Et nous devons installer le middleware express-session .

Faisons-le. Exécutez la commande suivante:

 npm install body-parser express-session

Une fois cela fait, créez un fichier index.js dans le dossier racine de votre application et ajoutez-y le contenu suivant:

 / * EXPRESS SETUP * /

const express = require ('express');
const app = express ();

app.use (express.static (__ dirname));

const bodyParser = require ('body-parser');
const expressSession = require ('express-session') ({
  secret: «secret»,
  réenregistrer: faux,
  saveUninitialized: false
});

app.use (bodyParser.json ());
app.use (bodyParser.urlencoded ({extended: true}));
app.use (expressSession);

const port = process.env.PORT || 3000;
app.listen (port, () => console.log ('App écoute sur port' + port));

Premièrement, nous avons besoin Express et créons notre application Express en appelant express () . Ensuite, nous définissons le répertoire à partir duquel servir nos fichiers statiques.

La ligne suivante nous voit exiger le middleware body-parser, qui nous aidera à analyser le corps de nos requêtes. Nous ajoutons également le middleware express-session pour nous aider à enregistrer le cookie de session.

Comme vous pouvez le voir, nous configurons express-session avec un secret pour signer le cookie d'ID de session (vous devrait choisir une valeur unique ici), et deux autres champs, resave et saveUninitialized . Le champ resave force la session à être sauvegardée dans le magasin de sessions, et le champ saveUninitialized force à enregistrer une session qui n'est pas initialisée dans le magasin. Pour en savoir plus sur eux, consultez leur documentation, mais pour l'instant il suffit de savoir que pour notre cas nous voulons les garder faux .

Ensuite, nous utilisons process.env.PORT pour définir le port sur la variable de port d'environnement si elle existe. Sinon, nous utiliserons par défaut 3000 qui est le port que nous utiliserons localement. Cela vous donne suffisamment de flexibilité pour passer du développement directement à un environnement de production où le port peut être défini par un fournisseur de services comme, par exemple, Heroku . Juste en dessous, nous avons appelé app.listen () avec la variable de port que nous avons configurée et un simple journal pour nous faire savoir que tout fonctionne bien et sur quel port l'application écoute.

tout pour la configuration Express. Nous allons maintenant configurer Passport .

Configurer Passport

Premièrement, nous installons Passport avec la commande suivante:

 npm install passport

Ensuite, nous devons ajouter les lignes suivantes au bas du fichier index.js :

 / * CONFIGURATION DU PASSEPORT * /

passeport const = exigé («passeport»);

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

Ici, nous avons besoin d'un passeport et l'initialisons avec son middleware d'authentification de session, directement dans notre application Express.

Création d'un magasin de données MongoDB

Puisque nous supposons que vous avez déjà installé Mongo, vous devriez pouvoir démarrer le shell Mongo en utilisant la commande suivante:

 mongo

Dans le shell, exécutez la commande suivante:

 use MyDatabase;

Cela crée simplement un magasin de données nommé MyDatabase .

Laissez le terminal là; nous y reviendrons plus tard.

Connexion de Mongo au nœud avec Mongoose

Maintenant que nous avons une base de données contenant des enregistrements, nous avons besoin d'un moyen de communiquer avec elle depuis notre application. Nous utiliserons Mongoose pour y parvenir. Pourquoi n'utilisons-nous pas simplement Mongo ordinaire? Eh bien, comme les développeurs de Mongoose aiment à le dire, A href = ”https://mongoosejs.com/docs/unstable/index.html”> sur leur site Web:

écrire la validation MongoDB, le casting et la plateforme de logique métier est un frein .

Mongoose va simplement nous faciliter la vie et rendre notre code plus élégant.

Allons de l'avant et installons-le avec la commande suivante:

 npm install mongoose

Nous utiliserons également passport-local-mongoose ce qui simplifiera l'intégration entre Mongoose et Passport pour l'authentification locale. Il ajoutera un champ de hachage et sel à notre schéma afin de stocker le mot de passe haché et la valeur de sel. C'est formidable, car les mots de passe ne doivent jamais être stockés en texte brut dans une base de données .

Installons le package:

 npm install passport-local-mongoose

Maintenant, nous devons configurer Mongoose. J'espère que vous connaissez maintenant l'exercice: ajoutez le code suivant au bas de votre fichier index.js :

 / * MONGOOSE SETUP * /

const mangouste = require ('mangouste');
const passportLocalMongoose = require ('passport-local-mongoose');

mongoose.connect ('mongodb: // localhost / MyDatabase',
  {useNewUrlParser: true, useUnifiedTopology: true});

const Schema = mangouste.Schema;
const UserDetail = nouveau schéma ({
  nom d'utilisateur: String,
  mot de passe: chaîne
});

UserDetail.plugin (passportLocalMongoose);
const UserDetails = mongoose.model ('userInfo', UserDetail, 'userInfo');

Ici, nous avons besoin des packages précédemment installés. Ensuite, nous nous connectons à notre base de données en utilisant mongoose.connect et lui donnons le chemin vers notre base de données. Ensuite, nous utilisons un schéma pour définir notre structure de données. Dans ce cas, nous créons un schéma UserDetail avec les champs username et password .

Enfin, nous ajoutons passportLocalMongoose comme un plugin pour notre schéma. Cela fera partie de la magie dont nous avons parlé plus tôt. Ensuite, nous créons un modèle à partir de ce schéma. Le premier paramètre est le nom de la collection dans la base de données. Le deuxième est la référence à notre schéma, et le troisième est le nom que nous attribuons à la collection dans Mongoose.

C'est tout pour la configuration de Mongoose. Nous pouvons maintenant passer à la mise en œuvre de notre stratégie de passeport.

Implémentation de l'authentification locale

Et enfin, c'est ce que nous sommes venus faire ici! Configurons l'authentification locale. Comme vous le verrez ci-dessous, nous allons simplement écrire le code qui va le configurer pour nous:

 / * AUTHENTIFICATION LOCALE DU PASSEPORT * /

passport.use (UserDetails.createStrategy ());

passport.serializeUser (UserDetails.serializeUser ());
passport.deserializeUser (UserDetails.deserializeUser ());

Il y a pas mal de magie ici. Tout d'abord, nous faisons passeport utiliser la stratégie locale en appelant createStrategy () sur notre modèle UserDetails - avec l'aimable autorisation de passport-local-mongoose - qui s'occupe de tout pour que nous n'ayons pas à mettre en place la stratégie.

Ensuite, nous utilisons les rappels serializeUser et deserializeUser . La première sera invoquée lors de l'authentification, et son travail consiste à sérialiser l'instance utilisateur avec les informations que nous lui transmettons et à la stocker dans la session via un cookie. Le second sera invoqué à chaque demande ultérieure de désérialisation de l'instance, en lui fournissant l'identifiant de cookie unique en tant que «justificatif d'identité». Vous pouvez en savoir plus à ce sujet dans la Documentation des passeports .

Itinéraires

Ajoutons maintenant quelques itinéraires pour tout lier ensemble. Tout d'abord, nous allons ajouter un package final. Accédez au terminal et exécutez la commande suivante:

 npm install connect-sure-login

Le package connect-assure-login est un middleware qui garantit qu'un utilisateur est connecté. Si une demande reçue non authentifiée est reçue, la demande sera redirigée vers une page de connexion. Nous allons l'utiliser pour protéger nos itinéraires.

Maintenant, ajoutez ce qui suit au bas de index.js :

 / * ROUTES * /

const connectEnsureLogin = require ('connect-sure-login');

app.post ('/ login', (req, res, next) => {
  passport.authenticate («local»,
  (err, utilisateur, info) => {
    si (err) {
      return next (err);
    }

    si (! utilisateur) {
      return res.redirect ('/ login? info =' + info);
    }

    req.logIn (utilisateur, fonction (err) {
      si (err) {
        return next (err);
      }

      return res.redirect ('/');
    });

  }) (req, res, suivant);
});

app.get ('/ login',
  (req, res) => res.sendFile ('html / login.html',
  {root: __dirname})
);

app.get ('/',
  connectEnsureLogin.ensureLoggedIn (),
  (req, res) => res.sendFile ('html / index.html', {root: __dirname})
);

app.get ('/ private',
  connectEnsureLogin.ensureLoggedIn (),
  (req, res) => res.sendFile ('html / private.html', {root: __dirname})
);

app.get ('/ user',
  connectEnsureLogin.ensureLoggedIn (),
  (req, res) => res.send ({utilisateur: req.user})
);

En haut, nous avons besoin de connect-sure-login . Nous y reviendrons plus tard.

Ensuite, nous avons configuré un itinéraire pour gérer une demande POST vers le chemin / login . À l'intérieur du gestionnaire, nous utilisons la méthode passport.authenticate qui tente de s'authentifier avec la stratégie qu'il reçoit comme premier paramètre - dans ce cas local . Si l'authentification échoue, il nous redirigera vers / login mais il ajoutera un paramètre de requête - info - qui contiendra un message d'erreur. Sinon, si l'authentification réussit, elle nous redirigera vers la route '/' .

Ensuite, nous configurons la route / login qui enverra la page de connexion. Pour cela, nous utilisons res.sendFile () et transmettons le chemin du fichier et notre répertoire racine, qui est celui sur lequel nous travaillons - d'où le __ dirname . [19659003] La route / login sera accessible à tous, mais pas la prochaine. Dans les itinéraires / et / privés nous enverrons leurs pages HTML respectives, et vous remarquerez quelque chose de différent ici. Avant le rappel, nous ajoutons l'appel connectEnsureLogin.ensureLoggedIn () . Voici notre garde-route. Son travail consiste à valider la session pour vous assurer que vous êtes autorisé à regarder cet itinéraire. Voyez-vous maintenant ce que je voulais dire plus tôt par «laisser le serveur faire le gros du travail»? Nous authentifions l'utilisateur à chaque fois.

Enfin, nous aurons besoin d'un itinéraire / utilisateur qui renverra un objet avec nos informations utilisateur. C'est juste pour vous montrer comment vous pouvez obtenir des informations du serveur. Nous demanderons cette route au client et afficherons le résultat.

En parlant du client, faisons-le maintenant.

Le client

Le client devrait être assez simple. Nous allons créer des pages HTML et un fichier CSS . Commençons par la page d'accueil ou l'index. Dans la racine de votre projet, créez un dossier appelé html et ajoutez un fichier appelé index.html . Ajoutez-y ce qui suit:




  
    Accueil 
  



    

Nous avons ici une balise h1 vide où nous placerons notre message de bienvenue et, en dessous, un lien vers / private . La partie cruciale ici est la balise de script en bas où nous allons gérer l'obtention du nom d'utilisateur pour créer le message de bienvenue.

Ceci est divisé en quatre parties:

  1. Nous instancions l'objet de requête en utilisant new XMLHttpRequest () .
  2. Nous avons défini la propriété onreadystatechange avec la fonction qui sera appelée après avoir obtenu notre réponse. Dans le rappel, nous vérifions si nous avons obtenu une réponse réussie et si oui, nous analysons la réponse, obtenons l'objet utilisateur (celui que nous avons envoyé dans la route / user vous vous souvenez?), Et nous recherchez l'élément message de bienvenue pour définir son innerText sur notre user.username .
  3. Nous ouvrons () ouvrons () le ] GET demande à l'utilisateur URL et nous définissons le dernier paramètre sur true pour le rendre asynchrone .
  4. Enfin, nous envoyer () la demande.

Nous allons maintenant créer la page de connexion. Comme précédemment, dans le dossier HTML, créez un fichier appelé login.html et ajoutez-y le contenu suivant:




    Login 
  



  

Login


Sur cette page, nous avons un formulaire de connexion simple, avec les champs nom d'utilisateur et mot de passe ainsi qu'un bouton Soumettre . En dessous, nous avons une étiquette où nous afficherons tous les messages d'erreur. Souvenez-vous, ceux-ci sont contenus dans la chaîne de requête.

La balise du script en bas est beaucoup plus simple cette fois. Nous instancions un objet URLSearchParams en passant la propriété window.location.search qui contient la chaîne de paramètres dans notre URL. Ensuite, nous utilisons la méthode URLSearchParams.get () en transmettant le nom du paramètre que nous recherchons.

À ce stade, nous avons un message d'information ou non. Donc, si nous le faisons, nous obtenons l'élément message d'erreur et définissons son innerText sur quel que soit ce message, puis définissons sa propriété style.display sur bloc . Cela le rendra visible, étant donné que par défaut, il a un affichage : valeur "none" .

Configurons maintenant la page privée. Encore une fois, créez un fichier dans le dossier HTML avec le nom private.html et ajoutez le contenu suivant:




    Private 
  



  

Ceci est un espace privé

Vous seul pouvez le voir

Retour   

Super simple. Juste un simple message et un lien Retour qui nous ramène à la page d'accueil.

C'est tout pour le HTML, mais comme vous l'avez probablement remarqué, nous référençons un CSS déposer les balises head . Ajoutons ce fichier maintenant. Créez un dossier appelé css à la racine de notre projet et ajoutez-y un fichier styles.css avec le contenu suivant:

 body {
  affichage: flex;
  align-items: centre;
  fond: # 37474F;
  famille de polices: monospace;
  couleur: # cfd8dc;
  justifier-contenu: centre;
  taille de police: 20px;
}

.messagerie {
  alignement du texte: centre;
}

une {
  couleur: azur;
}

.champ {
  marge: 10px;
}

contribution {
  famille de polices: monospace;
  taille de police: 20px;
  frontière: aucune;
  fond: # 1c232636;
  couleur: # CFD8DC;
  rembourrage: 7px;
  bordure: # 4c5a61 solide 2px;
  largeur: 300px;
}

.submit-btn {
  largeur: 100%
}

.Titre {
  marge: 10px 0px 20px 10px
}

#Message d'erreur {
  couleur: # E91E63;
  bloc de visualisation;
  marge: 10px;
  taille de police: grande;
  max-width: fit-content;
}

Cela rendra nos pages suffisamment décentes. Voyons ça!

Prenez un terminal pointant vers la racine du projet et exécutez la commande suivante:

 node index.js

Accédez maintenant à http: // localhost: 3000 / dans votre navigateur. Vous devez être redirigé vers la page de connexion. Si vous essayez d'accéder à http: // localhost: 3000 / private il devrait vous rediriger vers la page de connexion. Notre garde-route fait son travail.

Appuyez sur Ctrl + C dans la fenêtre du terminal pour arrêter notre serveur. Revenez ensuite au fichier index.js et, au bas du fichier, ajoutez les lignes suivantes:

 / * ENREGISTREZ CERTAINS UTILISATEURS * /

UserDetails.register ({nom d'utilisateur: 'paul', actif: faux}, 'paul');
UserDetails.register ({nom d'utilisateur: 'jay', actif: faux}, 'jay');
UserDetails.register ({nom d'utilisateur: 'roy', actif: false}, 'roy');

Ceci utilise la méthode du registre passeport-local-mangouste pour saler le mot de passe pour nous. Il nous suffit de le transmettre en texte brut.

Maintenant, nous exécutons node index.js . Les utilisateurs seront créés. Vous devriez commenter ces dernières lignes maintenant.

Vous vous souvenez du terminal shell MongoDB que nous avons laissé ouvert? Retournez-y et tapez:

 db.userInfo.find ()

Cela devrait montrer à vos trois utilisateurs et, comme vous pouvez le voir, le sel et le hachage occupent désormais une bonne partie de l'espace sur le terminal.

C'est tout ce dont nous avons besoin pour que l'application fonctionne. Nous avons terminé!

Retournez dans le navigateur, essayez de vous connecter avec l'une des informations d'identification que nous avons entrées et vous verrez le message de connexion avec le nom d'utilisateur donné.

Étapes suivantes

Nous ajouté les modules nécessaires pour que cette application fonctionne - rien de plus, rien de moins. Pour une application de production, vous devrez ajouter un autre middleware et séparer votre code en modules. Vous pouvez prendre cela comme un défi pour mettre en place un environnement propre et évolutif et le transformer en quelque chose d'utile!

La première et la plus simple chose que vous devriez essayer est d'ajouter la déconnexion en utilisant la demande de passeport .logout () .

Vous pouvez ensuite essayer d'implémenter un flux de registres. Vous aurez besoin d'un formulaire d'inscription et d'un itinéraire pour parler. Vous devez utiliser le UserDetails.register () que nous avons ajouté plus tôt comme modèle. Pour une confirmation par e-mail, vous devriez consulter nodemailer .

Une autre chose que vous pourriez faire est d'essayer d'appliquer ces concepts à une application d'une seule page. Peut-être en utilisant Vue.js et son routeur. Et voilà votre week-end!

Conclusion

Eh bien, nous sommes enfin à la fin. Dans cet article, nous avons appris à implémenter l'authentification locale à l'aide de Passport dans une application Node.js . Au cours de ce processus, nous avons également appris à se connecter à MongoDB à l'aide de Mongoose .

Ce n'était peut-être pas aussi facile pour vous que j'ai essayé de le peindre, mais au moins vous j'ai vu que cela devient plus facile avec ces outils qui font de la magie en arrière-plan, nous laissant nous soucier seulement de ce que nous essayons de construire.

Les outils «magiques» ne sont pas toujours idéaux, mais des outils réputés et entretenus activement aident nous écrivons moins de code - et le code que vous n'écrivez pas est du code que vous ne maintenez pas, et le code que vous ne maintenez pas est du code que vous ne cassez pas.

Aussi, gardez à l'esprit que si un outil est activement maintenu par une équipe de base, les chances sont qu'ils savent ce qu'ils font mieux que nous. Délégué chaque fois que possible.

J'espère que vous avez apprécié ce didacticiel et que vous avez peut-être trouvé l'inspiration pour votre prochain projet.




Source link