简体   繁体   中英

How to properly implement serializeUser with passport.js?

Okay, so I am just getting in to the MEAN stack, and I'm trying to build an app with Passport.js.

I'm just starting user serialization to maintain sessions. In their example, Passport uses this for serialization and deserialization:

passport.serializeUser(function(user, done) {
  done(null, user.id);
});

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

So, my question is this: is this example considered secure? If I understand this right, doesn't that mean that a client could just fake the user ID to become logged in as whichever user has that ID?

I guess what I'm asking is, is their example considered "secure" and a proper way of doing things, or is it expected that you will change these functions to generate unique serialization. If this is considered secure, then I think I'm missing something on how this works, and I'd love to be filled in.

On the other hand, if this is not secure and I am expected to write my own functions in place of these, would the following be a valid and secure way of doing this:

  • Upon serialization of a user, generate a random hash and put that in the user's database entry. Random hash is the serial that represents that user.
  • Upon deserialization, look up the random hash in the database and return the corresponding user. If the hash isn't found throw some kind of error.
  • When the user logs out, delete their serial hash from their entry in the database.

If my logic up until here is valid, what would be a proper way to generate this random hash?

Yes, that is how you do serialization / deserialization. The id is not received from the client.

Session information is stored to your local session store, eg. database, under a random ID. For example, express-session uses uid-safe to generate the session ID. This ID is set to a cookie which is then sent to the client.

When the client makes a request, the session ID is read from the cookie if it has not been tampered (usually the ID is signed with the secret you define when intializing sessions). Using this ID, the real session data is read from your local session store. This is where the id used in deserialization comes from.

Here is an example what a session object stored to MongoDB could look like:

{
  "_id" : "_RXnIfFeb_qH6AXMO2ounrxlJZPHkwda",
  "session" : "{\"cookie\":{\"originalMaxAge\":null,\"expires\":null,\"secure\":false,\"httpOnly\":true,\"path\":\"/\"},\"passport\":{\"user\":\"5614c62e4372842244660dcf\"}}"
}

The _id here is what is signed and sent in the cookie. The session string, decoded to JSON object, is:

{
  "cookie": {
    "originalMaxAge": null,
    "expires": null,
    "secure": false,
    "httpOnly": true,
    "path": "/"
  },
  "passport": {
    "user": "5614c62e4372842244660dcf"
  }
}

Here, passport.user is the actual user ID returned by my applications seralizeUser that is given to deserializeUser when a session is being loaded.

So what happens if you change the cookie content? If the cookie is signed, it will be invalidated because the altered value does not match the signature. If it is not signed, the value is used when querying session store. The query will not return anything because you changed the ID and there is no matching session in the database (unless you have found out / guessed the session ID of another active session - ie. performing session hijacking ).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM