I\'m using passportJS with express to authenticate user by local strategy. I have seen few articles regarding how passport is setup and the execution flow. Although most of
After a long time of searching I found this article which explains authentication flow very clearly.
- When the user submits the login form, a POST request to /login is made resulting in the execution of the passport.authenticate middleware we've set up.
- As the authenticate middleware for that route is configured to handle the local strategy, passport will invoke our implementation of the local strategy.
- Passport takes the req.body.username and req.body.password and passes it to our verification function in the local strategy.
- Now we do our thing: loading the user from the database and checking if the password given matches the one in the database.
- If everything went fine and we want the user to login we invoke done(null, user).
- Calling done will make the flow jump back into passport.authenticate. It's passed the error, user and additional info object (if defined).
- If the user was passed, the middleware will call req.login (a passport function attached to the request).
- This will call our passport.serializeUser method we've defined earlier.
- Express loads the session data and attaches it to the req. As passport stores the serialised user in the session
- passport.session middleware is a Passport Strategy which will load the user object onto req.user if a serialised user object was found in the server.
- passport.initialize is invoked on the request, it finds the passport.user attached to the session. Next, passport.session is invoked.
- The passport.session middleware calls passport.deserializeUser we've setup. Attaching the loaded user object to the request as req.user.
I hope it helps.
Since you are using PassportJS so i assume you must be having some idea about how it works. So i would add further information which i think would clear your doubt.
Passport configuration involves three pieces:
The answer to your question lies in 3rd piece, sessions.
If authentication succeeds, a session will be established and maintained via a cookie set in the user's browser. Each subsequent request will not contain credentials, but rather the unique cookie that identifies the session. In order to support login sessions, Passport will serialize and deserialize user
instances to and from the session.
According to your implementation only the user ID is serialized to the session, keeping the amount of data stored within the session small. When subsequent requests are received, this ID is used to find the user, which will be restored to req.user
In passports we are given option to write our own serialization and deserialization logic so that we can choose any appropriate database and not tied with strict rules.
So to summarise, after successful authentication, user object is serialised and stored in session, if you call req.user, then you would be able to retrieve the same user object.
You are using cookie based authentication. To answer it for you and maybe someone who is very new at everything, I will try to be very very detailed. So here's a scenario...
Let's imagine that, this user has already logged into our application previously, so there's a record inside of our Users collection that matches this profile, so server says: " Looks like you have the same google profile ID as user123(that we have saved on our DB). I need to give you some identifying token that says you are without a doubt: 'user123' and this token will identify you on any follow up request that is made to our servers"
At that point, to generate that little token or little identifying piece of information, we are going to define a function called 'serializeUser.' serializeUser is going to be automatically called by passport with our user model that we just fetched during the this very last step. So to explain, we're going to use that user model to generate our identifying piece of user information and after we do that we'll pass that identifying piece of information back to passport and so that passport can automatically stuff that little token into the user's cookie for us.
Now, once the user decides that they want to make some type of follow up request, for instance a list of post or a list of messages or whatever, from the browser back to our server, the cookie for that request will be automatically added in the request by the browser, passport is going to take that identifying piece of information from the cookie and then pass it into a second function called "deserializeUser," in which we are going to take that identifying token and turn it back into a user model that uniquely identify this user.
To conclude...
In the first process (seralizeUser), 'user' was a user model instance (a mongoose model, if using mongoose)... What we did is we turned that model into an id.
In the second process (deserializeUser), we are doing the exact opposite, turning an id into a mongoose model instance. And to do that we have to search or query our big'ol collection with all of our different users that exist inside of our DataBase (using findById), and after we find that very particular user, then we will call 'done' on that user, meaning we will return that user.