Understanding Passport.js for Beginners: A Simple Guide
Tags: authentication, webdev, oauth, passportjs
Published: 2024-01-17 17:26:33

If you're diving into web development, chances are you'll encounter Passport.js, a powerful authentication middleware for Node.js applications. This guide will break down Passport.js into three key components: strategy, middleware, and session handling.

## Passport Strategy

**What is a Strategy?**

Think of a strategy as the answer to the question, "How do you log in and identify the user?" It contains two main parts: the configuration and the handler function.

### Configuration:

* Settings to connect with an external API, if needed.
* Not every strategy requires configuration.

```js
// Example LocalStrategy configuration
const LocalStrategy = require('passport-local').Strategy;

passport.use(new LocalStrategy(
  (username, password, done) => {
    // Validate user credentials and return the local user
    // ...
  }
));
```

### Handler Function:

* Executed after a successful login for the specific strategy.
* Takes the login process payload and returns the local user.
* For example, FacebookStrategy deals with tokens and user profiles.

```js
// Example FacebookStrategy handler function
passport.use(new FacebookStrategy(
  {
    clientID: 'your-client-id',
    clientSecret: 'your-client-secret',
    callbackURL: 'your-callback-url',
  },
  (accessToken, refreshToken, profile, done) => {
    // Upsert the user in the database based on the Facebook profile
    // ...
    return done(null, user);
  }
));
```

_Pro Tip: Your app can use multiple strategies, such as local usernames/passwords, "Login with Facebook," or "Login with Google."_

## Middleware

**What is Middleware?**

Middleware is where you apply authentication to your user's experience, consisting of setup, the login flow, and checking if the user is logged in.

### Setup:

* Initialize and use Passport in your app.
* `passport.initialize()` creates the passport object on the request.
* `passport.session()` sets up serialize and deserialize methods.

```js
// Setup Passport middleware
app.use(passport.initialize());
app.use(passport.session());
```

### Login Flow:

* Set up a login URL for each strategy.
* Use `passport.authenticate('something')` for the internal strategy name.
* Strategies may have a callback endpoint for handling authentication flow.

```js
// Example login flow for LocalStrategy
app.post('/login', 
  passport.authenticate('local', { failureRedirect: '/login' }),
  (req, res) => {
    res.redirect('/');
  }
);
```

### isAuthenticated:

* Custom middleware to check if a user is logged in.
* Protect endpoints by ensuring they are authenticated.

```js
// Custom middleware to check if a user is authenticated
function isAuthenticated(req, res, next) {
  if (req.isAuthenticated()) {
    return next();
  }
  res.redirect('/login');
}

// Protect an endpoint using isAuthenticated middleware
app.get('/protected', isAuthenticated, (req, res) => {
  res.send('This is a protected endpoint');
});
```

## Session Handling

**What is Session Handling?**
Handles user sessions, ensuring they stay logged in across requests.

### `deserializeUser`:

* Called during passport.session().
* Takes a session token (from serializeUser) and returns the local user or false.

```js
// Example deserializeUser method
passport.deserializeUser((id, done) => {
  // Fetch the user from the database based on the user ID
  // ...
  done(null, user);
});
```

### `serializeUser`:

* Called after the Strategy handler.
* It takes the local user and returns a string stored in the session.
* The string is used in deserializeUser to identify the user in your database.

```js
// Example serializeUser method
passport.serializeUser((user, done) => {
  // Store the user ID in the session
  done(null, user.id);
});
```

By understanding these three components, you'll be well-equipped to implement secure authentication in your Node.js applications using Passport.js. Remember to explore the various strategies available to suit your specific authentication needs.