A peep beneath the hood of PassportJS' OAuth flow
Tags: javascript, passportjs, oauth, node
Published: 2018-12-03 21:50:36

---
title: A peep beneath the hood of PassportJS' OAuth flow
published: true
description: Understanding how  PassportJS takes care of OAuth stuff in our behalf
tags: javascript, passportjs, oauth, nodejs
cover_image: https://res.cloudinary.com/practicaldev/image/fetch/s--lcJEXtE5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1600/1%2AwfHtGpmW-e9nm12NZGFmBw.png
---

Libraries are great. They provide standardized, widely compatible and clean way of doing common tasks, abstracting away the details we usually don't care about. They help us not to worry about the specifics of authentication, database handling or form validation and just write the code for that thing we have in mind.

But then, what happens when something doesn't work as expected? How do you know what went wrong if you're just pushing buttons on a black box?

Sooner or later it's necessary to understand how our borrowed libraries do that _little thing they do_ 🎶 to figure out where we (or them) took a wrong turn and be able to correct it.

This was the case for me when I decided to learn about [PassportJS](http://www.passportjs.org) for a personal project. And in this article I intend to dig into what I found most elusive about handling an OAuth flow with PassportJS.

If you need a full tutorial on how to implement PassportJS for OAuth, as always, I recommend [the one by the wonderful Net Ninja on YouTube](https://www.youtube.com/watch?v=sakQbeRjgwg&list=PL4cUxeGkcC9jdm7QX143aMLAqyM-jTZ2x). Or if you just want a refresher about how to dance the OAuth, you can visit [my previous article](https://dev.to/anabella/dancing-with-oauth-emp) on the subject.

# Index
- Basic PassportJS setup
- Calling authenticate
- Road to the `verify` callback
- WTF is serialize and deserialize
- The complete login flow
- The authenticated request flow



---

### Basic PassportJS setup

These are the only things we need to get started: **a passport strategy** that's properly configured and **2 endpoints** (one for authorizing, the other for redirecting) .

{% gist https://gist.github.com/anabellaspinelli/f14dcc1a62ab3411792bd53834fabc1c %}

### Calling authenticate

The great thing about Passport is that you can register any number of strategies with it and then tell it which one to use according to the route that's being called, using the authenticate method, like so:

```javascript
passport.authenticate('github');
```

When you configure one of the strategies you'll have to define some parameters and also a **verify callback function** that will handle the user data it gets back from the provider.

The weird thing, at least for me, was the reason behind having to call `passport.authenticate()` in two different routes.

_But here's the trick:_

The **first** time `authenticate()` is called passport will try to find if it has a strategy by the name of the string you pass to the function previously registered. If it does, it'll start the OAuth dance by hitting the provider's authorize endpoint. If it doesn't find it, it'll just throw an error saying that strategy is unknown.

Now, the **second** time it's called is within a callback from the provider's OAuth server, in the **redirect** route. This time, though it looks exactly the same, Passport will detect that it's on the second stage of the OAuth flow and tell the strategy to use the temporary code it just got to ask for an OAuth token. The strategy knows exactly how and where to ask for that. 

What happens after this?

### Road to the verify callback

Have a look at my latest hand drawn creation, a diagram about the OAuth flow in PassportJS. At this point we're reaching that red bubble that says `getProfile()`:

![Hand drawn diagram](https://cdn-images-1.medium.com/max/1600/1*wfHtGpmW-e9nm12NZGFmBw.png)


If this makes you more confused than before, read on; I promise it gets better!

The first thing that happens after we get the OAuth token is that the strategy fetches that user's profile. This is an internal mechanism of the strategy that knows **where** to ask for it on that specific provider.
 
Right after that, the strategy will try to parse the profile into a model it has defined internally for that provider, and then pass it with all the other data it has (accessToken, refreshToken and profile) to our **verify callback**.

Remember we defined the verify callback when we configured the strategy? Now is the first time our custom code in there gets executed by the strategy. In this instance we could check the database for that user, create a record for it if necessary and verify anything else that's needed.

Once we've checked all that we needed, we'll call done (or _the callback of the verify callback_) which is its fourth and last function argument. We'll pass it `null` (for no errors) and the user with all the information we find relevant.

```javascript
(accessToken, refreshToken, profile, done) => {
  // verify things here and then...
  done(null, {accessToken, profile})
}
```

And finally, Passport will execute its very own `req.login()` which will save that user into `req.user` for further use.
 
_Check that diagram up there again, you should understand it much better now._

Up next comes `serializeUser` 👇

### WTF is serialize and deserialize

> Serialization is the process of translating data structures or object state into a format that can be stored or transmitted and reconstructed later.
––Wikipedia's **Serialization** Article

In our case, "the data" is that user we've been tossing around. Our own custom code in Passport's `serializeUser` method should define what pieces of information we need to persist into the session in order to be able to retrieve the full user later by passing it to serializeUser's `done` callback. 

    
This is Passport's serialize user method in a very simple form: 

```javascript
passport.serializeUser((user, done) => done(null, {
  id: user.profile.id,
  accessToken: user.access_token
}))
```
☝️this object will end up in `req.user` and `req.session.passport.user` for subsequent requests to use.

Now for `deserializeUser`, this function will  receive the user data present in the session and use it to get all of the user's data from our DB. For example:

```javascript
passport.deserialize((user, done) => {
  dbHelper.getUser(user.id)
    .then(profile => done(profile))
})
```

Whatever gets passed to `done` here will be available in `req.user`.
 
### The complete login flow

Let's  do a zoom-in of the previous diagram, specifically after the OAuth dance is over. I wanted to dig deeper into that because I remember it being particularly mysterious when I was starting to use PassportJS for OAuth.

![Close up of previous drawn diagram](https://cdn-images-1.medium.com/max/1600/1*e4qfhVz49TSrAw1IQQ6tBQ.png)

So this is what happens after the user says "yes, allow" and our app gets their access token:

- Passport receives an OAuth token from the provider
- It uses it to fetch the user's profile information
- The `verifyCallback` runs, and when it's done it passes the user object to its own `done`  callback
- Passport calls its own method `req.login()` which then calls `serializeUser()`.
serializeUser extracts some user info to save in the session and then continues with the following handlers of the redirect route.

### The authenticated request flow
Now, this is all very nice, but how does our app know that the user is still authenticated on further requests and that it can provide private information safely? 

This is not a full tutorial, but if you've been following one, you probably have something like this in your server code:

```javascript
server.use(passport.initialize())
server.use(passport.session())
```

These lines configure two _middlewares_ that will run on every request that our server gets.

When an authenticated request is made, Express will load the session into the req, making our serialized user data available at `req.session.passport.user`.

Then, the first middleware, `initialize()`, will try to find that user in the request, or create it as an empty object if it doesn't exist (which would mean the user is not authenticated). 

And then, `session()` will kick in which to determine if the request is authenticated by trying to find a serialized object in it.
 
When it finds it, it'll pass it to `deserializeUser` which will use it to get the whole user data (maybe from the DB) and add it to `req.user` where we can use it to create other requests.

So, even though `serializeUser` **is only called on log in**, `deserializeUser` is a global middleware that'll get executed on every single request to make the full user object available for authenticated requests.

---

_This concludes my deep dive into the OAuth flow which I hope has helped you to understand what is going on behind the scenes of PassportJS at least a bit better. It surely helped me clear some doubts to write it. Thanks for reading!_

_While I was researching for this article I came across this wonderful [unofficial documentation for PassportJS](https://medium.com/r/?url=https%3A%2F%2Fgithub.com%2Fjwalton%2Fpassport-api-docs) by J. Walton's which will surely help you in any other doubts you might have._