DEV Community

Cover image for Just Which Way Does The Auth Flow? #3
James F. Thomas
James F. Thomas

Posted on • Updated on

Just Which Way Does The Auth Flow? #3

The Switch In The Flow From Authenticate to Authorize

Introduction:

Last time we concluded our exploration of the OAuth process with the secrete calling of the req.login() function. Remember that it is just one of the little perks of putting Passport.js middleware functions into our project. So, thank you very much Passport.js, and now we can move on up to serialize. At this point in our control flow, having completed authentication, our user information is being passed from the done() function in our Verify Callback to the next function in the chain, serializeUser(). This function marks the establishment of a new user session and the last level of our exploration.

What is a user session?

During my research, I encountered several different ways people defined user session, but for our purposes, we will think of it as a cache of requests a user makes during a specific time period. This time begins at the invocation of req.login() and ends, of course, when you call req.logout(). But wait there is some Passport.js hidden magic going on again. The logout() function is exposed on the request object, and will be called inside the route handler. It is extremely easy to miss this connection, I know I did, mostly because of the differences in scope. So instead of logout() is found in that chain of Passport.js functions we set up in the authentication strategy, it’s called when the user is on the way out the door, like turning off the lights when the user clicks logout.

Code Example: logOut() function invocation in route handler

apiRouter.get('/logout', (req, res) => {
  req.logOut();
  req.session.destroy();
  res.redirect('/');
});

Enter fullscreen mode Exit fullscreen mode

In the above code block, you can visualize where the logout() function is invoked. This code block was housed in a sperate file from the OAuth strategy setup used in my project and illustrates how someone could leave it out of their map of the control flow. Let’s backtrack a bit before we forget about serializeUser().

So where does serialize fit in?

Remember that serialization occurs between login and logout functions, once the user’s information is passed from our verify callback to serilazeUser() at the beginning of our user session. The job of the serailizeUser() function is to translate certain user data, in this case, the id, into a format that can be stored within a session cookie. The session cookie is sent to the browser and maintained for the length of the session. The baking and decorating of session cookies is a treat we’ll cover another time.

Code Example: Passport.js serializeUser() function

passport.serializeUser((user, done) => {
  done(null, user);
});

Enter fullscreen mode Exit fullscreen mode

When we examine the code block above you see that serializeUser() accepts two arguments, the user object, and the done() function. It is at this point that serializeUser() will designate what user information to translate into the session cookie by passing it to done. Once done has been invoked our code is passed onto deserializeUser() which will then locate a user within our database that matches the translated data. This serialization and deserialization of user information allows our application to keep all user data safe server-side, while the cookie will only contain a session id that is used to continuously authorize that user’s requests throughout the life of the session.

Code Example: implementation of Passport.js deserializeUser() function

passport.deserializeUser((user, done) => {
  getUser(user) 
    .then((foundUser) => {
      if (foundUser) {
        done(null, foundUser);
      } else {
        console.log('no user with that id found');
      }
    })
    .catch((error) => {
      console.log(error);
    });
  });

Enter fullscreen mode Exit fullscreen mode

If the session hasn’t expired or the user hasn’t hit the logout route, the serialize/deserialize set will be working to keep that user happy providing information to their authorized requests. One function I missed mentioning earlier was the destroy() function. This method is part of the Express.js framework and not native to the Passport.js control flow unless you specifically choose to employ it in your applications’ structure. The destroy() method will destroy the session cookie, subsequently ending that users authorization, and requiring the entire OAuth process be restarted for future requests to be served.

Conclusion:

At this point, we have explored all the levels as well as players involved in those steps that need to be taken in order to authenticate and authorize a user. I know that I learned a few very interesting things and it is my hope that you did too. Biggest take away from this whole dive:

Authentication is the process of proving you are who you say you are, while Authorization is the process of being allowed to go into certain areas, use certain services, or view specific content. Here's a fun little analogy: All crew sailors can get permission to come aboard the ship, but only certain members can eat in the officer's mess.

I'll be back soon, to tackle some new topics. I've been told by many teachers that the more you write, the more you grow, so to ensure my development skills continue to grow I will write continuously.

Happy Coding!!!

Alt Text

Sources:

Discussion (0)