Why is passport.serializeUser executed on each request?

泄露秘密 提交于 2019-12-18 12:04:08

问题


I am using passport.js + passport-facebook-token to secure my API build with Strongloop's Loopback Framework.

Why is passport serializing the deserialized user again after it has successfully been deserialized? Also the passport.authenticate method is called on every request! What am I doing wrong?

Here is node's log:

deserializeUser, id: XXXXXXXXXXXXXXXX
User found.
serializeUser, id: XXXXXXXXXXXXXXXX
GET /api/events?access_token=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX 304 182ms

Here is the js code:

passport.use(new FacebookTokenStrategy({
    clientID: XXXXXXXXXXXXXXXX,
    clientSecret: 'XXXXXXXXXXXXXXXXXXXXXXXXXXXX'
  },
  function(accessToken, refreshToken, profile, done) {
    //check user table for anyone with a facebook ID of profile.id
    User.findOne({
      'facebookId': profile.id
    }, function(err, user) {
      if (err) {
        return done(err);
      }
      if (user) {
        console.log("User found.");
        return done(err, user);
      } else {
        console.log("User not found.");
        User.create({
          email: profile.emails[0].value,
          facebookId: profile.id,
          password: 'secret'
        }, function(err, user) {
          console.log(user.id);
          console.log(user.email);
          console.log(user.facebookId);
          console.log("User created");
          return done(err, user);
        });
      }
    });
  }));

passport.serializeUser(function(user, done) {
  console.log('serializeUser, id: ' + user.facebookId);
  done(null, user.facebookId);
});

passport.deserializeUser(function(id, done) {
  console.log('deserializeUser, id: ' + id);
  User.findOne({
    'facebookId': id
  }, function(err, user) {
    if (!err) {
      done(null, user);
    } else {
      done(err, user);
    }
  });
});

回答1:


Regarding your question about why passport.authenticate is called on every request, it is because you defined it as a middleware, probably before any routing logic happens.

If you have private and public sections on your app, you could do something like that :

// Define a specific that will handle authentication logic
app.get("/auth", passport.authenticate('facebook-token',function(){...});

// Public sections which do not require authentication
app.get("/public1",...);
app.post("/public2",...);

// Private sections which do require authentication
app.get("/private1", function(req,res,next){
   if (req.isAuthenticated()){ // Check if user is authenticated
       // do things...
   }else{ // Wow, this guy is not authenticated. Kick him out of here !
       res.redirect("/auth");
   }
});

Now, if you have multiple private sections, you'll probably find it a bit tidious to do the same thing for each private section. You could define a custom function that will check if the user is authenticated, and allow the request to proceed if he is. Something like

function isThisGuyAuthenticated(req,res,next){
   if (req.isAuthenticated()){
      return next(); // Ok this guy is clean, please go on !
   }else{
      res.redirect("/auth"); // This guy is shady, please authenticate !
   }
}

And use it like :

app.get("/private1",isThisGuyAuthenticated, doCrazySecretStuff); // doCrazySecretStuff will not be called if the user is not authenticated
app.get("/private2", isThisGuyAuthenticated, getCocaColaRecipe);
app.get("/private3", isThisGuyAuthenticated, flyToMars);
app.get("/public", showInfo); // showInfo will be called whether the user is authenticated or not

Now, if your app only has private sections, you could avoid repeating calls to isThisGuyAuthenticated by defining it as middleware (but not by defining passport.authenticate itself as a middleware !);

// Endpoint that will be hit is the user is redirected to /auth
// BEWARE it needs to be above the middleware, otherwise you'll end up with an infinite redirection loop
app.get("/auth", passport.authenticate('facebook-token',function(){...});

// Middleware that will be called on every request
app.use(isThisGuyAuthenticated);

// You app's endpoints
app.get("/private1", doCrazySecretStuff); // doCrazySecretStuff will not be called if the user is not authenticated
app.get("/private2", getCocaColaRecipe);
app.get("/private3", flyToMars);

Is that clear ?

EDIT : I mistakenly put the middleware before the "/auth" endpoint. Make sure it's placed after



来源:https://stackoverflow.com/questions/24888214/why-is-passport-serializeuser-executed-on-each-request

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!