Juin 2016

Volume 31, numéro 6

Cet article a fait l'objet d'une traduction automatique.

Le travail programmeur - comment être moyenne : Passport

Par Ted Neward | Juin 2016

Ted NewardBienvenue, MEANers.

J’ai fait une tonne de travail côté serveur et cela devient proche du moment que je démarre le transfert sur l’extrémité cliente d’éléments. Avant cela, cependant, il est autre chose qui doit absolument aborder avant que je peux faire la transition entièrement. En particulier, je dois pouvoir prendre en charge des utilisateurs. La plupart des applications (si ce n’est pas tous, à ce stade) nécessitent un certain type de mécanisme d’authentification utilisateur pour établir l’identité d’un utilisateur, en général, vous pouvez de limiter les données qui vous indiquent les ou les options qui vous permettent de faire au sein du système.

Bien qu’il soit toujours tentant de « déployer votre propre » au sein de la Communauté de nœud, qui est simplement donc 2010 ! La bonne réponse à un de ces types de Dilemmes est toujours « atteindre npm », et dans ce cas, le vainqueur incontesté généralisée autour des systèmes d’authentification est une bibliothèque Node.js appelée Passport.

Passport

À ce stade, il doit être facile à déterminer quelles sont les premières étapes d’utilisation de la bibliothèque de Passport ; Rechercher le nom de package npm et « npm install ». Le nom de package npm peut être détecté en recherchant dans le Registre npm en ligne ou en visitant la page d’accueil de Passport. Toutefois, tout d’abord visiter PassportJS.org offre de deux morceaux de choix intéressant:, que toutes autres Node.js package page d’accueil déjà écrit, contrairement à la commande « npm install » n’est pas présente ici sur la première page ; deux, que Passport a apparemment ce concept de « stratégies », et il est important.

C’est pour une raison simple : Lorsque vous dites: « il est temps pour authentifier les informations d’identification de l’utilisateur, » qui est en fait une instruction vague. Non seulement existe-t-il des diverses informations d’identification différentes qui peut être utilisé pour authentifier, il existe des milliers ou plus différentes informations d’identification stockent (à des serveurs) sur lequel un utilisateur peut s’authentifier. Passport souhaite être la solution pour tout type d’authentification par rapport à n’importe quel type de banque d’informations d’identification, Facebook, LinkedIn, Google ou votre propre base de données locale et utilise une grande variété de types d’informations d’identification, à partir du nom d’utilisateur/mot de passe via les jetons Web JSON pour les en-têtes HTTP porteur et bien d’autres éléments que vous pouvez êtes.

Cela signifie alors que Passport n’est pas le seul package ; est un package de passport principal et il n’y a stratégies (307 d'entre eux, en fait, au moment de la rédaction de cet article) pour comment Passport consiste à faire le travail réel de l’authentification. Le choix de la stratégie (ou des stratégies, j’y reviendrai que dans un instant) définit le package réel requis, qui à son tour définit les éléments à installer. (Mais, heure de la publication de vérité, Passport définit en fait un package de base « passport » qui sera utilisé par les autres stratégies concernés, afin d’obtenir un saut de choses en effectuant un « npm install--enregistrer passport » avant de plonger dans les détails de la stratégie).

Bonjour, Local

Stratégie et de loin le plus courant (en particulier pour les systèmes qui sont construites sur des magasins de bases de données / d’informations d’identification utilisateur interne) est la stratégie « locale ». C’est le standard, « Client envoie un nom d’utilisateur et un mot de passe, et vous comparer par rapport à..., tout ce que vous stockez les noms d’utilisateur et mots de passe dans. » Il est sans doute pas aussi sûre que certains des autres stratégies, mais elle est un bon point de départ.

Pour le moment, dans le code j’ai travaillé avec, il n’y a eu aucune authentification que ce soit. Par conséquent, nous allons garder les choses simples à coder simplement un nom d’utilisateur/mot de passe fixe en place. Une fois que vous voyez comment Passport fonctionne, il est relativement facile de voir où le code pour une recherche de base de données accède à faire la comparaison, je vais laisser.

Ayant décidé que je souhaite utiliser la stratégie locale de passport, commencer avec « npm install--enregistrer passport local » pour obtenir les bits nécessaires passport en place. (N’oubliez pas, le «--enregistrer « argument le place dans le fichier manifeste de package afin que les aurez sont automatiquement suivie en tant que dépendance formelle.)

Une fois installé, je dois faire trois choses : one, configurer Passport pour utiliser la stratégie donnée ; deux, établir l’itinéraire d’URL HTTP auquel l’utilisateur sera envoie la demande d’authentification ; trois, configurez le middleware Express pour exiger une authentification avant d’autoriser l’utilisateur accéder à l’URL HTTP en question.

Configuration

Je vais commencer par prise Passport chargé dans l’application en premier. En supposant que passport et passport locales ont déjà été installées, j’ai besoin de les charger dans le fichier app.js script via classiques nécessitent magique :

var express = require('express'),
  bodyParser = require('body-parser'),
  // ...
  passport = require('passport'),
  LocalStrategy = require('passport-local').Strategy;

Notez que le LocalStrategy a la valeur légèrement différente. comme MongoClient précédemment, vous en fait d’affecter LocalStrategy le résultat de l’accès au champ « Stratégie » de l’objet retourné par l’appel requis. Cette is'nt commune dans Node.js, mais elle n’est pas si rare qu’ils soient uniques. LocalStrategy dans ce cas va servir à un type de classe à instancier (ou en tant que proche en tant que JavaScript peuvent généralement get).

Je dois également indiquer à l’environnement Express que Passport est sur la tâche :

var app = express();
app.use(bodyParser.json());
app.use(passport.initialize());

L’appel d’initialize est relativement explicite. Il sera préparation Passport pour vous préparer à recevoir des demandes entrantes. Souvent, vous allez être un appel semblable à passport.session par utilisateur configurer des sessions, similaires à celle que vous voyez dans ASP.NET, mais d’une API HTTP que je crée ici, qui est moins souvent nécessaire ou souhaitable (je parlerai que dans quelques instants).

Défi

Ensuite, je dois établir le rappel appelle lorsqu’il reçoit une demande d’authentification Passport. Ce rappel effectuera le travail de recherche de l’utilisateur et valider le mot de passe passés. (Ou, dans un scénario réel plus, recherche de l’utilisateur et de valider que le hachage de mot de passe salés est le même que le hachage de mot de passe salés actuellement stocké dans la base de données, mais ce n’est vraiment plus en dehors de l’étendue de Passport lui-même.) Cela est fait en appelant passport.use et en passant une instance de la stratégie à utiliser, avec le rappel incorporé dans celui-ci, comme indiqué dans Figure 1.

Figure 1 l’établissement du rappel

passport.use(new LocalStrategy(
  function(username, password, done) {
    debug("Authenticating ",username,",",password);
    if ((username === "sa") && (password == "nopassword")) {
      var user = {
        username : "ted",
        firstName : "Ted",
        lastName : "Neward",
        id : 1
      };
      return done(null, user);
    }
    else {
      return done(null, false, { message: "DENIED"} );
    }
  }
));

Plusieurs choses se passent ici. Tout d’abord, au moment où que le rappel est appelé, Passport a déjà effectué le travail de l’analyse de la demande entrante et l’extraction du nom d’utilisateur et le mot de passe à transmettre à ce rappel. Pour le LocalStrategy, Passport suppose que ces valeurs sont passées dans via les paramètres nommés respectivement les nom d’utilisateur et mot de passe. (Cela est configurable dans l’appel de construction LocalStrategy, si ce ne sont pas acceptables.)

Ensuite, le mécanisme de vérification est entièrement en dehors de la compétence de Passport. Il part du principe que les stratégies effectuera la vérification, et dans ce cas, la stratégie « locale » qui diffère uniquement au code d’application. Dans cet exemple, vous venez de vérifier par rapport à une valeur codée en dur, mais dans des cas plus classiques, ce serait une recherche Mongo pour un utilisateur dont nom d’utilisateur correspond à ce qui a été passé, puis une vérification de mot de passe.

Troisièmement, en fonction du style de middleware Node.js habituel, réussite ou l’échec est signalé à l’aide de la fonction terminée, avec les paramètres passés indiquant si réussite ou l’échec a eu lieu. Succès signifie que le deuxième paramètre est un objet utilisateur qui est placé dans l’objet de demande d’Express qui a été passée plus loin dans le pipeline ; Échec provoque Passport à poser Express pour renvoyer une réponse 401 (non autorisé) et peut éventuellement inclure le message d’échec, généralement utilisé pour les messages « flash » par rapport à l’interface utilisateur. (Si les messages flash ne sont pas utilisées, le message est effectivement rejeté.)

Conséquences

À présent, tout cela reste consiste à configurer l’itinéraire par lequel l’authentification a lieu :

app.post('/login',
  passport.authenticate('local', { session: false }),
  function(req, res) {
    debug("user ", req.user.firstName, " authenticated against the system");
    res.redirect("/persons");
  });

Passport ne soucie particulièrement le modèle d’URL nouveautés qui effectue l’authentification ; /login est simplement une convention, mais /signin ou /user/auth ou tout d’une demi-douzaine autres variétés est entièrement raisonnable. La clé est que la première étape lors de la résolution de cet itinéraire est d’appeler le passeport authentifier fonction, en passant dans la stratégie à utiliser (local), s’il faut utiliser les cookies de session par l’utilisateur (qui, comme déjà indiqué, est particulièrement adapté à une API) et la fonction réelle à appeler si l’authentification réussit. Ici, cette fonction enregistre simplement un message à déboguer et redirige ensuite l’utilisateur à la liste des personnes stockées dans la base de données.

À présent, je peux tester cela en passant un contenu de formulaire publié ou par l’envoi de contenu JSON ; comme il s’agit d’une API, il est probablement plus facile et d’envoyer un paquet JSON :

{ "username" : "sa" , "password" : "nopassword" }

Si le nom d’utilisateur et le mot de passe correspondent, le succès et une redirection 302 à /persons est retourné ; Si ce n’est pas le cas, puis renvoie une réponse 401 est renvoyée. Cela fonctionne !

La redirection du trafic

Dans les faits, il commune de modèle (lors de la création d’une application de Web côté serveur traditionnelle à l’aide rapide) qu’une authentification réussie dirige l’utilisateur à un itinéraire donné, tandis qu’une défaillance à suivre l’utilisateur vers une nouvelle page, et pour cette raison, Passport permet une approche plus simple pour l’authentification de rappels :

app.post('/login',
  passport.authenticate('local', { successRedirect: '/',
                                   failureRedirect: '/login',
                                   failureFlash: true })
);

Ici, en cas de réussite, Passport est automatiquement redirigée vers l’URL « / » et en cas d’échec, à la « / connexion « URL, et (dans ce cas) avec un bref message indiquant que l’utilisateur n’a pas pu se connecter avec succès.

Dans le cas d’une API, cependant, il est plus courante pour obtenir une représentation JSON de l’objet utilisateur pour le client pour l’affichage et modification. N’oubliez pas, cependant, que rien n’est lié à la sécurité ou sensibles jamais être envoyé comme partie de ce, aucun mot de passe, en particulier. Les navigateurs sont toutes extrêmement utiles pour fournir des utilitaires de débogage côté client, et par conséquent, tout intrus peut très facilement atteindre dans cet objet utilisateur contenu dans la mémoire du navigateur et démarrer la modification immédiatement pour leur semble. Qui peut être incorrecte. (Ces objets JSON peuvent également être falsifiées « en vol » demander plus Node.js API systèmes pour s’exécuter sur HTTPS, au lieu de HTTP. Heureusement, la plupart du temps, configuration Express pour exécuter via HTTPS au lieu de HTTP est plus un exercice de configuration cloud que toute modification apportée par programmation.) Par conséquent, les mots de passe ne doivent jamais laisser le serveur, et « rôles » (pour un système d’autorisation par rôle) doivent toujours être vérifiées à partir de la base de données, et non à partir de l’objet utilisateur transmise la demande.

Rédaction, toutefois, maintenant le client API devez passer de l’authentification des informations d’identification chaque fois que le « / connexion « itinéraire est atteint et les informations d’identification ne sont pas activées sur un des autres itinéraires. Bien que je certainement est susceptible de vérifications d’authentification sur tous les itinéraires (et devrait, sont à considérer), je ne souhaitez probablement obligé de passer les informations d’identification dans le cadre de chaque appel de méthode.

Alternatives

Passport a cette idée couverte « de pique, » comme on le dit.

Tout d’abord, vous pouvez toujours revenir à activer les sessions ; Lorsque les sessions sont sur, Passport crée un identificateur unique et les renvoyer en tant que partie de la réponse HTTP en tant que cookie. Les clients doivent ensuite rendent ce cookie dans le cadre de chaque demande. La principale exigence sur le serveur à ce stade est que la bibliothèque Passport a besoin de savoir comment transformer un objet utilisateur dans un identificateur et inversement ; ils appellent cette sérialisation et la désérialisation d’un utilisateur, et elle nécessite de configurer des rappels de méthode pour chacun de ces deux points de terminaison Passport :

passport.serializeUser(function(user, done) {
  done(null, user.id);
});
passport.deserializeUser(function(id, done) {
  User.findById(id, function(err, user) {
    done(err, user);
  });
});

La fonction serializeUser est conçue pour fournir un identificateur unique pour l’utilisateur à Passport (de sorte que je s’en emparer hors du champ user.id) et la fonction deserializeUser effectue l’opération inverse (de sorte que j’utilise l’id transmis en tant que la clé primaire dans une recherche de base de données pour l’objet utilisateur dans son ensemble).

Vous pouvez activer les sessions pour la plupart, sinon toutes les stratégies de Passport, mais en général qu'il fonctionne lorsque le serveur génère HTML pour être interprétés directement par le navigateur. API tendance à ne pas fonctionner si les cookies presque autant, en particulier parce que les API est souvent atteints par les clients de l’application mobile natif autant que, ou plus souvent qu’un client basé sur navigateur.

Une deuxième approche utilise une autre stratégie de Passport qui s’appuie sur un « secret connu » au client et serveur. Cela peut être transmis de plusieurs façons. Dans certains cas, le système gère un ensemble connu d’émis « clés de l’API », et vous devez fournir cette clé dans le cadre de chaque demande. Cela est assez courante avec un nombre de services REST de tiers, mais elle présente une faille dans la mesure où si un attaquant peut obtenir la clé, le pirate peut usurper l’identité du client jusqu'à ce que le client réinitialise la clé. Passport fournit une stratégie pour cela ; Utilisez « npm installer--enregistrer passport-localapikey ». Il comporte de la même façon que la stratégie locale, sauf à présent la méthode d’authentification de stratégie recherche la clé d’API dans la base de données, plutôt que le nom d’utilisateur et le mot de passe.

Utilise une approche similaire de JSON Web Tokens (Jwt), qui sont plus sécurisés, mais nécessitent un espace beaucoup plus de temps à expliquer que nous avons ici ; « npm install--enregistrer passport-jwt » met dans le projet. Jwt est un ensemble compressé d’un ensemble d’éléments de données différents, une d’elles peut être un secret partagé (à API de la clé ou le mot de passe), mais permettre être vérifiée pour émetteurs particuliers, public et bien plus encore.

Ou, par exemple, l’objectif n’est pas enregistrer tout type d’informations d’identification du tout, mais s’appuient sur des systèmes tiers (tels que Facebook, Google, Twitter, LinkedIn ou de plusieurs centaines autres sites populaires) pour effectuer l’authentification. Passport a couvert ici, aussi, avec des stratégies pour chacun de ces sites individuellement, comme les stratégies ainsi que généralisée OAuth 2.0 (et OpenID, pour les sites qui l’utiliser).

Je pense que le point devient clair : Si vous pouvez l’imaginer un système d’authentification, Passport a une stratégie déjà définie. Simplement « npm install », définir la configuration, de placer l’appel de l’autorisation dans les itinéraires Express et les extraire.

Par ailleurs, il semble important de souligner qu’il existe des services sur Internet qui fournit un seul point de contrôle d’accès pour tous ces problèmes d’authentification. Ces services « Authentification-as-a-Service » deviennent de plus en plus populaires comme le nombre de sites qui utilisent régulièrement proliférer et deviennent de plus en plus d’un véritable casse-tête administratif. Un de Mes favoris, Auth0 (qui a en fait quelques personnes ex-Microsoft dans le côté technique de l’entreprise), est un commanditaire du projet Passport et ses logos et les icônes apparaissent discrètement dispersés dans tout le site Passport. Je vous encourage fortement de la récupération si le projet n’a pas encore une stratégie d’authentification prédéfinie en place (par exemple, un système hérité ou d’intégrer sur Facebook ou échange, ou que vous avez).

Synthèse

Passport est sans doute les projets d’authentification plus jamais développées sur n’importe quel langage ou plate-forme de. Il gère fournir l’authentification requise « hooks » tout en laissant ouvert le moyen réel d’authentification lorsque vous souhaitez contrôler, encore glissement dans et faire qu’essentiel lorsque vous n’avez pas. L’approche de stratégie signifie qu’il est extensible à l’infini et peut contenir toute sorte de nouveau schéma d’authentification qui peut-être émerger, même de 20 ans dans le futur. (Ne pas rire, JavaScript, en fait, resteront exécuter 20 ans à partir de maintenant. Vous regardez.)

Mais Passport est définie presque autant grâce à ce qu’il ne fait pas comme résultat ; Il punts complètement sur une idée de l’autorisation basée sur les rôles et il n’essaie pas de résoudre tout type de chiffrement ou de chiffrement. Passport est toutes les informations d’identification de la vérification, qui, bien sûr par ce point rend le nom beaucoup plus clair, comme lorsque je voyage en Europe, je dois afficher mon compte passport pour prouver que je suis un citoyen américain, Passport nécessite que les utilisateurs affichent leurs informations d’identification afin qu’ils puissent s’ils sont des citoyens d’arriérés au sein du système.

Une fois encore, je me trouve hors espace et de temps, c’est le cas pour l’instant... bon codage !


Ted Newardest mentor, conférencier et consultant de polytechnology basée à Seattle. Il a écrit plus de 100 articles, est MVP F # et a rédigé et coécrit une dizaine d’ouvrages. Contactez-le à ted@tedneward.com. Si vous souhaitez qu’il vienne travailler avec votre équipe, ou lire son blog à l’adresse blogs.tedneward.com.

Merci aux experts techniques suivants d'avoir relu cet article : Shawn Wildermuth