How to implement Google Authentication with NextJS and Passport.
Tags: javascript, react, nextjs, typescript
Published: 2022-03-28 22:01:24

### Introduction 
Recently I decided to use [NextJS](https://nextjs.org/) on a project and after so many iterations, I decided to use google authentication with [passport](https://www.passportjs.org/). In this article, I would be giving a step by step guide on how to set up authentication in your NextJS application with passport google strategy.

### Essentials
Before we get started on the main course, here are a few things you need to know and have set up. 

- You need to have basic knowledge of Javascript or Typescript as well as React (NextJS). 
- You need to understand the concept of http requests and responses.
- You should have [Node](https://nodejs.org/en/download/) set up on your computer.
- You must have set up your application on [Google developers console](https://console.cloud.google.com/)... you can check 'Register Application' section [here](https://github.com/jaredhanson/passport-google-oauth2/blob/master/README.md) on how to go about it.

In this article, I would be using [`yarn`](https://yarnpkg.com/) as my package manager, you could go ahead to use `npm` if you prefer. 


---

First you would need to set up a NextJS project on your computer, so you go to your terminal to run the following command

```
yarn create next-app --typescript
```
You would be prompted to enter a name for the project, do so and press enter to proceed. 
Once the set up is complete, you need to change directory to the newly setup project by running the next command 

```
cd <your-project-name>
```

Next up, you install all the dependencies you need to successfully complete your authentication implementation which  include:

- [next-connect](https://www.npmjs.com/package/next-connect)
- [passport](https://github.com/jaredhanson/passport)
- [passport-google-oauth20](https://www.npmjs.com/package/passport-google-oauth20)

To install, run the following command in your terminal 

```zsh
yarn add next-connect passport passport-google-oauth20 @types/passport @types/passport-google-oauth20
```

Next up, You need to add some credentials to your env file. Create a new file named `.env` and add the following values 

```txt
GOOGLE_CLIENT_ID: <your app client id>
GOOGLE_CLIENT_SECRET: <your app client secret>
```

After this, you can now go into writing the main code. 

Now, we start coding!

In your root directory, create a new folder called `lib`. Inside the `lib` folder, create a new file named `passport-google-auth.ts`

In the `passport-google-auth.ts` file, you configure google strategy using passport using the following code. 

```ts
// /lib/passport-google-auth.ts

import { Profile, Strategy as GoogleStrategy } from "passport-google-oauth20";
import passport from "passport";

// logic to save your user or check if user exists in your record to proceed.
const saveUser = (user: Profile) => {
  return new Promise((resolve, reject) => {
    resolve("Successful");
  });
};

passport.use(
  new GoogleStrategy(
    {
      clientID: process.env.GOOGLE_CLIENT_ID as string,
      clientSecret: process.env.GOOGLE_CLIENT_SECRET as string,
      callbackURL: "/api/oauth2/redirect/google", // this is the endpoint you registered on google while creating your app. This endpoint would exist on your application for verifying the authentication
    },
    async (_accessToken, _refreshToken, profile, cb: any) => {
      try {
        await saveUser(profile);
        return cb(null, profile);
      } catch (e: any) {
        throw new Error(e);
      }
    }
  )
);


// passport.serializeUser stores user object passed in the cb method above in req.session.passport
passport.serializeUser((user, cb) => {
  process.nextTick(function () {
    return cb(null, user);
  });
});

// passport.deserializeUser stores the user object in req.user
passport.deserializeUser(function (
  user: any,
  cb: (arg0: null, arg1: any) => any
) {
  process.nextTick(function () {
    return cb(null, user);
  });
});

// for broader explanation of serializeUser and deserializeUser visit https://stackoverflow.com/questions/27637609/understanding-passport-serialize-deserialize

// An article that explains the concept of process.nextTick https://nodejs.dev/learn/understanding-process-nexttick

export default passport;

```

Next up, you create a new file in `/pages/api` folder named `login.ts`. 
Inside the `login.ts` file, you create a get request that uses the google strategy method you configured with passport in the last step by adding the following code: 

```ts
// /pages/api/login.ts

import passport from "../../lib/passport-google-auth";
import nextConnect from "next-connect";

export default nextConnect()
  .use(passport.initialize())
  .get(
    passport.authenticate("google", {
      scope: ["profile", "email"],
    })
  );
```

You will now create the callback url for verifying the authentication. 
Go to `api` folder in `pages`, create a folder named `oauth2`. Inside the `oauth2` folder, create a folder named `redirect`. Inside the `redirect` folder, create a new file named `google.ts`.

```ts
// /pages/api/oauth2/redirect/google.ts

import { NextApiRequest, NextApiResponse } from "next";
import nextConnect from "next-connect";
import passport from "../../../../lib/passport-google-auth";

export default nextConnect().get(
  passport.authenticate("google"),
  (req: NextApiRequest & { user: any }, res: NextApiResponse) => {
    // you can save the user session here. to get access to authenticated user through req.user
    res.redirect("/");
  }
);

```

Now that you are done implementing the backend, you can now use the endpoints on the frontend. 
Create a file named login in the pages folder and paste the following code for your login page.

```tsx
// /pages/login.tsx

import Link from "next/link";

const LoginPage = () => {
  return (
    <div
      style={{
        display: "flex",
        flexDirection: "column",
        justifyContent: "center",
        alignItems: "center",
        height: "100%",
        width: "100%",
        textAlign: "center",
      }}
    >
      <h1 style={{ fontSize: "2.5rem" }}>Login with Google</h1>
      <Link href="/api/login" passHref>
        <button
          style={{
            border: "1px solid black",
            backgroundColor: "white",
            borderRadius: "10px",
            height: "50px",
            width: "200px",
            cursor: "pointer",
          }}
        >
          Proceed
        </button>
      </Link>
    </div>
  );
};

export default LoginPage;
```
Voila, you can now authenticate your next app with google. 

### Conclusion
This article shows how you can leverage passport google strategy to authenticate your users in your next app. 
You can access the code used in this tutorial [here](https://github.com/haywhy43/nextjs-passport-google-authentication-tutorial).


### Disclaimer
This is my first technical article and I hope I did justice to the topic. Questions or feedback can be dropped in the comments. You can follow me on [twitter](https://twitter.com/ayomikun_elijah) and [github](https://github.com/haywhy43)