web-dev-qa-db-fra.com

PassportJS deserializeUser jamais appelé

J'ai configuré Passport pour authentifier les utilisateurs stockés dans mongodb. Semble fonctionner correctement: l'authentification réussit/échoue correctement et les variables de session sont définies. Cependant, obtenir que Passport vérifie si une session a échoué. Il semble y avoir un problème en ce sens que les instructions console.log que j'ai ajoutées au rappel deserializeUser ne voient jamais la lumière du jour. Je suppose que mon problème est lié au fait que deserializeUser ne soit jamais appelé. Toute personne capable de diagnostiquer mon faux pas?

// Passport configuration
passport.serializeUser(function(user, cb){ cb(null, user.id) });
passport.deserializeUser(function(uid, cb){
  console.log("Trying to deserialize user: "+uid);
  User.findById(uid, function(err, user){
    cb(err, user);
  });
});
// auth strategy function
passport.use(new LocalStrategy({usernameField: 'email'},
  function(email, pass, done){
    User.findOne({email: email}, function (err, user) {
      if (err)
        return done(err);
      if (!user)
        return done(null, false, {message: "Couldn't find user"});
      var crypted = bcrypt.hashSync(pass, user.salt);
      if(user.hashpass != crypted)
        return done(null, false, {message: "Bad password"});
      return done(null, user);
    });
  }
));

passport.CreateSession =  function (req, res, next) {
  passport.authenticate('local', function(err, user, info){
    if(err || !user)
      return res.json({status: "Failure: "+err});
    req.logIn(user, function (err){
      if(err)
        return res.json({status: "Failure: "+err});
      return res.json({status: "Authenticated"});
    });
  })(req, res, next);
};

avec ce qui suit dans app.js:

app.post('/session', passport.CreateSession); // restify better
app.del('/session', passport.DestroySession);
app.get('/images', passport.CheckSession, routes.images);
33
Alex Westholm

Pour tous ceux qui ont ce problème, jetez un oeil à ceci:

app.use(session({ 
    secret: 'something', 
    cookie: { 
        secure: true
    }}));

Si cookie.secure est défini sur true et que vous n'utilisez PAS SSL (protocole https), le cookie contenant l'identifiant de session n'est pas renvoyé au navigateur et tout échoue en mode silencieux. Supprimer ce drapeau a résolu le problème pour moi - cela a pris des heures pour le réaliser!

30
Dave Kerr

Si vous utilisez le rappel authenticate lorsque vous vous authentifiez avec un passeport, vous devez connecter l'utilisateur manuellement. Il ne sera pas appelé pour vous.

passport.authenticate('local', function (err, user) {
    req.logIn(user, function (err) { // <-- Log user in
       return res.redirect('/'); 
    });
})(req, res);
23
Rick

Avez-vous use() 'd passport.session()? Comme dans cet exemple:

https://github.com/jaredhanson/passport-local/blob/v1.0.0/examples/login/app.js#L91

C'est ce qui restaure la session et appelle deserializeUser, donc il semblerait que cela manque peut-être.

11
Jared Hanson

D'accord, cela m'a pris presque 3 jours pour résoudre, ce qui semble être une solution simple, au moins dans mon cas. J'ai dû placer les app.use(require('cookie-parser')); et app.use(require('express-session')({ secret: 'keyboard cat', resave: false, saveUninitialized: false })); AVANT d'appeler le:

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

Remarque: Ces extraits ne sont pas mon code réel, je l’ai extrait de: https://github.com/passport/express-4.x-local-example > fichier server.js; mais c'est l'essentiel de celui-ci.

1
Sharukh Mastan

Je me suis battu le même problème toute la journée. J'avais un rappel personnalisé configuré pour faire des autorisations (comme au bas de http://passportjs.org/guide/authenticate/ ). Il semblerait que Passport pré-traite tous les objets de requête avant même qu’ils n’atteignent l’autre middleware (sur la base de certaines instructions de journalisation que j’ai écrites). Dans le cadre de ce prétraitement, il place les informations utilisateur désérialisées dans l'objet request.user. Malheureusement, le comportement par défaut de passport.authenticate ('local', rappel) semble ignorer les données de session ou de cookie et supposer que le nom d'utilisateur et le PW sont envoyés dans l'objet de requête. Pour résoudre ce problème, j'ai tout d'abord vérifié l'objet request.user. S'il existait, cela signifiait que Passport avait effectué son prétraitement et que je pouvais alors appeler directement le login. Voici ma fonction d'autorisation, que j'utilise à la place de passport.authenticate ('local'):

function doAuth(request, response, next)
{ 

if (request.user) {
    request.logIn(request.user, function (err) {
        if (err) {
            console.log(err);
            response.status(500).json({message:
                    "Login failed. Auth worked. Nonsense"});
            return;
        }
        console.log("doAuth: Everything worked.");
        next();
    });
    return;
}

passport.authenticate('local', function(err, user, info) {
    if (err) {
        response.status(500).json({message: "Boo Passport!"});
        return; //go no further
        //until I figure out what errors can get thrown
    }
    if (user === false) {
        console.log("Authentication failed. Here is my error:");
        console.log(err);
        console.log("Here is my info:");
        console.log(info);
        response.status(500).json({message: "Authentication failed."});
        return;
    }
    request.logIn(user, function(err) {
        if (err) {
        console.log("Login failed. This is the error message:");
        console.log(err);
        response.status(500).json({message:"Login failed."});
            return;
        }
        console.log("doAuth: Everything worked. I don't believe it.");

        next();
    });
})(request, response, next);

 }
1
user3522492

Aujourd'hui, j'ai rencontré le même problème, et dans mon cas, la cause était la façon dont le côté client effectue les appels d'API. Et l'approche suivante m'a aidé à surmonter le problème:

const doFetch(url, method = 'GET', body) {
  const headers = new Headers();
  headers.append('Content-Type', 'application/json');
  headers.append('Accept', 'application/json');
  headers.append('Cache', 'no-cache');
  const params = { 
    method, headers, 
    credentials: 'include' // The cookie must be sent!
  }
  if(body) {
    params.body = body;
  }
  return fetch(url, params);
}

Après cela, deserializeUser a commencé à être appelé correctement.

0
dhilt