web-dev-qa-db-fra.com

bibliothèques d'authentification utilisateur pour node.js?

Existe-t-il des bibliothèques d'authentification d'utilisateur existantes pour node.js? En particulier, je recherche quelque chose qui puisse authentifier un mot de passe pour un utilisateur (à l'aide d'une base de données d'authentification d’arrière-plan personnalisée) et associer cet utilisateur à une session.

Avant d'écrire une bibliothèque d'authentification, je pensais que je verrais si les gens connaissaient les bibliothèques existantes. Impossible de trouver quelque chose d'évident via une recherche google.

-Shreyas

272
shreddd

On dirait que le plugin connect-auth du middleware connect correspond exactement à ce dont j'ai besoin: http://wiki.github.com/ciaranj/connect-auth/creating-a-form-based-strategy

J'utilise express [ http://expressjs.com ], de sorte que le plugin connect s'intègre très bien, car express est sous-classé (ok - prototypé) à partir de connect

26
shreddd

Si vous recherchez un cadre d’authentification pour Connect ou Express, Passport mérite d’être étudié: https://github.com/jaredhanson/passport

(Divulgation: je suis le développeur de Passport)

J'ai développé Passport après avoir enquêté sur connect-auth et everyauth. Bien qu'ils soient tous deux d'excellents modules, ils ne répondaient pas à mes besoins. Je voulais quelque chose de plus léger et discret.

Passport est divisé en modules distincts, vous pouvez donc choisir de n'utiliser que ce dont vous avez besoin (OAuth, uniquement si nécessaire). De plus, Passport ne monte aucun itinéraire dans votre application, ce qui vous donne la possibilité de décider quand et où vous voulez l'authentification et vous permet de contrôler ce qui se passe lorsque l'authentification réussit ou échoue.

Par exemple, voici le processus en deux étapes pour configurer une authentification basée sur un formulaire (nom d'utilisateur et mot de passe):

passport.use(new LocalStrategy(
  function(username, password, done) {
    // Find the user from your DB (MongoDB, CouchDB, other...)
    User.findOne({ username: username, password: password }, function (err, user) {
      done(err, user);
    });
  }
));

app.post('/login', 
  passport.authenticate('local', { failureRedirect: '/login' }),
  function(req, res) {
    // Authentication successful. Redirect home.
    res.redirect('/');
  });

Des stratégies supplémentaires sont disponibles pour l'authentification via Facebook, Twitter, etc. Des stratégies personnalisées peuvent être connectées, si nécessaire.

232
Jared Hanson

Session + Si

Je suppose que la raison pour laquelle vous n’avez pas trouvé beaucoup de bonnes bibliothèques est que l’utilisation d’une bibliothèque pour l’authentification est généralement trop sophistiquée.

Ce que vous recherchez n'est qu'un classeur de session :) Une session avec:

if login and user == xxx and pwd == xxx 
   then store an authenticated=true into the session 
if logout destroy session

c'est ça.


Je ne partage pas votre conclusion selon laquelle le plugin connect-auth est la solution.

J'utilise aussi connect mais je n'utilise pas connect-auth pour deux raisons:

  1. IMHO casse connect-auth de l’architecture très puissante et facile à lire en anneau de connexion. Un non-aller - mon avis :). Vous pouvez trouver un très bon article sur le fonctionnement de connect et l’idée de la rondelle d’oignon ici .

  2. Si vous - comme écrit - voulez simplement utiliser un login de base ou http avec une base de données ou un fichier. Connect-auth est trop gros. C'est plus pour des choses comme OAuth 1.0, OAuth 2.0 & Co


Une authentification très simple avec connect

(C'est complet. Exécutez-le simplement pour le tester, mais si vous voulez l'utiliser en production, assurez-vous d'utiliser https.) (Pour être conforme au principe REST, vous devez utiliser une requête POST au lieu d'une requête GET b/c vous changez d'état :)

var connect = require('connect');
var urlparser = require('url');

var authCheck = function (req, res, next) {
    url = req.urlp = urlparser.parse(req.url, true);

    // ####
    // Logout
    if ( url.pathname == "/logout" ) {
      req.session.destroy();
    }

    // ####
    // Is User already validated?
    if (req.session && req.session.auth == true) {
      next(); // stop here and pass to the next onion ring of connect
      return;
    }

    // ########
    // Auth - Replace this example with your Database, Auth-File or other things
    // If Database, you need a Async callback...
    if ( url.pathname == "/login" && 
         url.query.name == "max" && 
         url.query.pwd == "herewego"  ) {
      req.session.auth = true;
      next();
      return;
    }

    // ####
    // This user is not authorized. Stop talking to him.
    res.writeHead(403);
    res.end('Sorry you are not authorized.\n\nFor a login use: /login?name=max&pwd=herewego');
    return;
}

var helloWorldContent = function (req, res, next) {
    res.writeHead(200, { 'Content-Type': 'text/plain' });
    res.end('authorized. Walk around :) or use /logout to leave\n\nYou are currently at '+req.urlp.pathname);
}

var server = connect.createServer(
      connect.logger({ format: ':method :url' }),
      connect.cookieParser(),
      connect.session({ secret: 'foobar' }),
      connect.bodyParser(),
      authCheck,
      helloWorldContent
);

server.listen(3000);

REMARQUE

J'ai écrit cette déclaration il y a plus d'un an et je n'ai actuellement aucun projet de nœud actif. Il y a donc des modifications d’API dans Express. S'il vous plaît ajouter un commentaire si je devrais changer quelque chose.

89
Matthias

Je cherchais fondamentalement la même chose. Plus précisément, je voulais ce qui suit:

  1. Pour utiliser express.js, qui englobe les fonctionnalités de middleware de Connect
  2. Authentification "basée sur le formulaire"
  3. Contrôle granulaire sur les routes authentifiées
  4. Une base de données pour les utilisateurs/mots de passe
  5. Utiliser des sessions

J'ai fini par créer ma propre fonction de middleware check_auth que je transmets en tant qu'argument à chaque route à authentifier. check_auth vérifie simplement la session et si l'utilisateur n'est pas connecté, il les redirige ensuite vers la page de connexion, comme suit:

function check_auth(req, res, next) {

  //  if the user isn't logged in, redirect them to a login page
  if(!req.session.login) {
    res.redirect("/login");
    return; // the buck stops here... we do not call next(), because
            // we don't want to proceed; instead we want to show a login page
  }

  //  the user is logged in, so call next()
  next();
}

Ensuite, pour chaque route, je m'assure que cette fonction est passée en tant que middleware. Par exemple:

app.get('/tasks', check_auth, function(req, res) {
    // snip
});

Enfin, nous devons réellement gérer le processus de connexion. C'est simple:

app.get('/login', function(req, res) {
  res.render("login", {layout:false});
});

app.post('/login', function(req, res) {

  // here, I'm using mongoose.js to search for the user in mongodb
  var user_query = UserModel.findOne({email:req.body.email}, function(err, user){
    if(err) {
      res.render("login", {layout:false, locals:{ error:err } });
      return;
    }

    if(!user || user.password != req.body.password) {
      res.render("login",
        {layout:false,
          locals:{ error:"Invalid login!", email:req.body.email }
        }
      );
    } else {
      // successful login; store the session info
      req.session.login = req.body.email;
      res.redirect("/");
    }
  });
});

Quoi qu'il en soit, cette approche a été principalement conçue pour être simple et flexible. Je suis sûr qu'il existe de nombreuses façons de l'améliorer. Si vous en avez, j'aimerais beaucoup vos commentaires.

EDIT: Ceci est un exemple simplifié. Dans un système de production, vous ne voudrez jamais stocker et comparer les mots de passe en texte brut. Comme le souligne un commentateur, certaines bibliothèques peuvent aider à gérer la sécurité des mots de passe.

14
Tom

Jetez également un œil sur everyauth si vous souhaitez une intégration de connexion de tiers/réseau social.

13
Peter Lyons

Voici un code pour l’authentification de base de l’un de mes projets. Je l'utilise contre CouchDB avec un cache de données d'authentification supplémentaire, mais j'ai supprimé ce code.

Enroulez une méthode d’authentification autour de votre demande et fournissez un deuxième rappel pour une authentification infructueuse. Le rappel de succès obtiendra le nom d'utilisateur en tant que paramètre supplémentaire. N'oubliez pas de gérer correctement les demandes avec des informations d'identification incorrectes ou manquantes dans le rappel d'échec:

/**
 * Authenticate a request against this authentication instance.
 * 
 * @param request
 * @param failureCallback
 * @param successCallback
 * @return
 */
Auth.prototype.authenticate = function(request, failureCallback, successCallback)
{
    var requestUsername = "";
    var requestPassword = "";
    if (!request.headers['authorization'])
    {
        failureCallback();
    }
    else
    {
        var auth = this._decodeBase64(request.headers['authorization']);
        if (auth)
        {
            requestUsername = auth.username;
            requestPassword = auth.password;
        }
        else
        {
            failureCallback();
        }
    }


    //TODO: Query your database (don't forget to do so async)


    db.query( function(result)
    {
        if (result.username == requestUsername && result.password == requestPassword)
        {
            successCallback(requestUsername);
        }
        else
        {
            failureCallback();
        }
    });

};


/**
 * Internal method for extracting username and password out of a Basic
 * Authentication header field.
 * 
 * @param headerValue
 * @return
 */
Auth.prototype._decodeBase64 = function(headerValue)
{
    var value;
    if (value = headerValue.match("^Basic\\s([A-Za-z0-9+/=]+)$"))
    {
        var auth = (new Buffer(value[1] || "", "base64")).toString("ascii");
        return {
            username : auth.slice(0, auth.indexOf(':')),
            password : auth.slice(auth.indexOf(':') + 1, auth.length)
        };
    }
    else
    {
        return null;
    }

};
7
b_erb

Une approche différente de l’authentification est Passwordless, un = authentification basée sur un jeton pour exprimer qui contourne le problème inhérent aux mots de passe [1]. Il est rapide à mettre en œuvre, ne nécessite pas trop de formulaires et offre une meilleure sécurité à l'utilisateur moyen (divulgation complète: je suis l'auteur).

[1]: Les mots de passe sont obsolètes

4
florian

Quelques années ont passé et j'aimerais présenter ma solution d'authentification pour Express. Cela s'appelle Lockit . Vous pouvez trouver le projet sur GitHub et une courte introduction sur mon blog .

Alors, quelles sont les différences avec les solutions existantes?

  • facile à utiliser: configurez votre base de données, installer npm, require('lockit'), lockit(app), c'est fait
  • itinéraires déjà intégrés (/ inscription,/login,/mot de passe oublié, etc.)
  • vues déjà intégrées (basées sur Bootstrap mais vous pouvez facilement utiliser vos propres vues)
  • il prend en charge la communication JSON pour vos applications à page unique AngularJS/Ember.js
  • il ne supporte PAS OAuth et OpenID. Seulement username et password.
  • il fonctionne avec plusieurs bases de données (CouchDB, MongoDB, SQL) prêtes à l'emploi
  • il a des tests (je n'ai trouvé aucun test pour cloison sèche)
  • il est activement maintenu (comparé à chaque automne)
  • vérification de l'email et processus du mot de passe oublié (envoi d'email avec jeton, non pris en charge par Passport)
  • modularité: utilisez uniquement ce dont vous avez besoin
  • flexibilité: personnalise tout

Jetez un coup d'oeil au exemples .

3
zemirco

Voici deux bibliothèques Github populaires pour l'authentification de nœud js:

https://github.com/jaredhanson/passport (suggestible)

https://nodejsmodules.org/pkg/everyauth

2
Soman Dubey

Il existe un projet appelé Drywall qui implémente un système de connexion utilisateur avec Passport et possède également un panneau d’administration de gestion des utilisateurs. Si vous recherchez un système de gestion et d’authentification d’utilisateur complet, similaire à ce que Django a mais pour Node.js, c’est ça. J'ai trouvé qu'il s'agissait d'un très bon point de départ pour la création d'une application de nœud nécessitant un système d'authentification et de gestion des utilisateurs. Voir réponse de Jared Hanson pour plus d'informations sur le fonctionnement de Passport.

2
lk145

Exemple simple et rapide d’utilisation de mongo, pour une API fournissant une authentification d’utilisateur pour c.-à-d. Angular client

dans app.js

var express = require('express');
var MongoStore = require('connect-mongo')(express);

// ...

app.use(express.cookieParser());
// obviously change db settings to suit
app.use(express.session({
    secret: 'blah1234',
    store: new MongoStore({
        db: 'dbname',
        Host: 'localhost',
        port: 27017
    })
}));

app.use(app.router);

pour votre itinéraire quelque chose comme ceci:

// (mongo connection stuff)

exports.login = function(req, res) {

    var email = req.body.email;
    // use bcrypt in production for password hashing
    var password = req.body.password;

    db.collection('users', function(err, collection) {
        collection.findOne({'email': email, 'password': password}, function(err, user) {
            if (err) {
                res.send(500);
            } else {
                if(user !== null) {
                    req.session.user = user;
                    res.send(200);
                } else {
                    res.send(401);
                }
            }
        });
    });
};

Ensuite, dans vos itinéraires nécessitant une autorisation, vous pouvez simplement vérifier la session de l'utilisateur:

if (!req.session.user) {
    res.send(403);
}
1
Mister P

Voici une nouvelle bibliothèque d'authentification qui utilise des jetons horodatés. Les jetons peuvent être envoyés par courrier électronique ou par SMS aux utilisateurs sans qu'il soit nécessaire de les stocker dans une base de données. Il peut être utilisé pour une authentification sans mot de passe ou pour une authentification à deux facteurs.

https://github.com/vote539/easy-no-password

Divulgation: Je suis le développeur de cette bibliothèque.

0
sffc