javascript - Why is passport.serializeUser executed on each request? - Stack Overflow

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

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);
    }
  });
});

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);
    }
  });
});
Share Improve this question edited Jan 7, 2015 at 8:22 Martijn Pieters 1.1m321 gold badges4.2k silver badges3.4k bronze badges asked Jul 22, 2014 at 13:04 electronix384128electronix384128 6,74312 gold badges47 silver badges67 bronze badges 3
  • 1 Could you show the code where you define the middleware handling your authentication ? It should look something like passport.authenticate("facebook", function ....). If you did something like app.get("/*", passport.authenticate()), it works as expected. – Waldo Jeffers Commented Jul 22, 2014 at 13:54
  • This is the only loc that is added for this: app.use(passport.authenticate('facebook-token')); – electronix384128 Commented Jul 22, 2014 at 14:39
  • hmm, ok i see. but my understanding was that it should be added as middleware, since it is protecting my api from unauthorized access... where would be the right place to add this line? or what do you suggest? – electronix384128 Commented Jul 22, 2014 at 15:40
Add a ment  | 

1 Answer 1

Reset to default 7

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

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745140121a4613390.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信