NextAuth - Google And GitHub Authentications for Nextjs
Published: 2022-08-18 15:56:00

---
canonical_url: https://refine.dev/blog/nextauth-google-github-authentication-nextjs/
---


## Introduction
We know how exhausting and time-consuming it can be to set up authentication, which includes handling databases, cookies, JWT, sessions, etc., on your own.
The goal of this article is for you to learn about an alternative and simple tool (NextAuth), which we will use to easily add Google and GitHub authentication to our application.

Steps we’ll cover:
- [What is NextAuth?](#what-is-nextauth)
- [Why use NextAuth.js?](#why-use-nextauthjs)
- [Project setup](#project-setup)
- [Create API Routes](#create-api-routes)
- [Configure Shared Session State](#configure-shared-session-state)
- [Update Page Components](#update-page-components)
- [Add React Hook](#add-react-hook)
- [Protect API Routes](#protect-api-routes)


## Prerequisites
We will be building a simple landing page to demonstrate how you can simply add Google and GitHub authentication to your Next.js app, and to follow along, you need to have the following in place:
- Node.js 12.22.0 or later
- Google console account.
- Github account.


## What is NextAuth?
[NextAuth.js](https://next-auth.js.org/) is an easy-to-implement open source authentication library originally designed for Nextjs and serverless. With NextAuth, you don’t necessarily have to create and use any database or any backend of any kind for authentication because it takes care of all that. It allows your users to sign in with their favorite preexisting logins. You can add as many predefined providers provided by NextAuth to your applications.


## Why use NextAuth.js?
- It supports OAuth 1.0, 1.0A, 2.0, and OpenID Connect and is designed to work with any OAuth service.
- Many popular sign-in services are already supported.
- Email and passwordless authentication are supported.
- Allows for stateless authentication with any backend (Active Directory, LDAP, etc.)
- JSON Web Tokens and database sessions are both supported.
- Designed for Serverless but runs anywhere (AWS Lambda, Docker, Heroku, and so on…).
- An open-source solution that gives you control over your data *
- MySQL, MariaDB, Postgres, SQL Server, MongoDB, and SQLite are all supported natively.
- Excellent compatibility with popular hosting provider databases
- It can be used without a database (for example, OAuth + JWT).
- Secure by default

## Project setup

To create a project, run:
```
yarn create next-app
```
The command above creates a new Next.js app using `create-next-app`, which sets up everything automatically for you. You will be prompted to enter your project name to complete the installation. We used the `yarn` package manager here, feel free to use `npm` if you have to.

Once the installation is completed, move into your folder directory and run the below command to start the project:

```
yarn dev
```

Now your app has started you need to install the NextAuth package which is essential for the authentications. 

```
yarn add next-auth
```
Once this is done, you will have all the dependencies required to follow up with this tutorial set up and can proceed with s authentication in your next application.

*If you are using TypeScript, NextAuth.js comes with its types definitions within the package. To learn more about TypeScript for next-auth, check out the [TypeScript documentation](https://next-auth.js.org/getting-started/typescript)*


## Create API Routes
To get started with adding NextAuth.js to your project, you first create a new folder named `auth` inside the `pages/api` directory. Inside this new folder, you will create a file called `[...nextauth].js`.

This will contains the dynamic route handler for `NextAuth.js` which will also contain all of your global `NextAuth.js` configurations. 

Next, inside the `[...nextauth].js` you've created, you will configure the global `NextAuth` configurations for `Github` and `Google` providers.



```ts
// pages/api/auth/[...nextauth].js

import NextAuth from "next-auth"
import GoogleProvider from "next-auth/providers/google";
import GithubProvider from "next-auth/providers/github"

export default NextAuth({
  // Configure one or more authentication providers
  providers: [
    GoogleProvider({
      clientId: process.env.GOOGLE_CLIENT_ID,
      clientSecret: process.env.GOOGLE_CLIENT_SECRET
    }),
    GithubProvider({
      clientId: process.env.GITHUB_ID,
      clientSecret: process.env.GITHUB_SECRET,
    }),
    // ...add more providers here
  ],
})
```
Looking at the code snippet above, we started by importing `NextAuth` from the next-auth package we installed earlier, and since we will be adding only Google and Github auth in this tutorial, `GoogleProvider` and `GithubProvider` were also imported and passed in the `providers` array which stores all `NextAuth` providers.

Next, we will be looking into how we can obtain the `clientId` and `clientSecret` for each of the providers.

### For GoogleProvider (Make sure you have a Google account):

Navigate to your [Google console](https://console.developers.google.com/apis/credentials) credentials tab.

![Create a Google project](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/w5wwk1hfg4rhztkp1swu.jpeg)

If you have created and selected a project before now, you will see a button at the top that says ***"CREATE CREDENTIALS"*** but if you haven't you need to create a project by clicking on the ***"CREATE PROJECT"*** action button like the one circled in the image above. You will be taken to a page where you will enter your project name and organization (optional).

When that is done, ensure you select the project you just created when notified.

![Select Google project](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6j99p5jutyu6dbbr0r7m.png)

Once that is done, proceed to create credentials by clicking on the "CREATE CREDENTIALS" action button at the top, this will open a dropdown containing four items. Click on the item circled in the below image to create an OAuth client ID.



![Select auth](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kzqmgii34o1c9hytvq5u.png)

If you come across anything like:

> To create an OAuth client ID, you must first configure your consent screen

Please, go ahead to configure the consent screen by providing some information on your app, and when that is done, proceed to continue creating the OAuth client ID by choosing the application type and filling up the rest of the fields.

![Google select auth](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/p5vzg3f187218t18y56w.png)


After entering the name of your OAuth 2.0 client. You will see a section that requests adding an **"Authorised JavaScript origins"**, click on the "+ ADD URI" action button to add your app origin. Since we are working in the development environment, all we need to do is to copy/paste our app URL which is running on localhost.


![Authorised origins](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8t1siwswwwhc5aquv8r9.png)



For the **"Authorised redirect URIs"**, you must include your full domain and end in the callback path.
* For production: `https://{YOUR_DOMAIN}/api/auth/callback/google`
* For development: `http://localhost:3000/api/auth/callback/google`

![Redirect URL](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/azuvhjh4xf5btiv7psrq.png)



**Note:** 
If you eventually push to production, you need to change the Authorised JavaScript Origin and Authorised redirect URIs to the production URIs.



Please verify the details provided and if they are all correct, click on "CREATE" to finally create your OAuth client ID.

![Auth client verified](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9ug0cz0w8q8euhe7zcli.png)


Congratulations! You've successfully created Google OAuth client ID and SECRET. 

Where do you store it?

Next, you will create a `.env.local` file in the root level of your app folder and inside of it you will create `GOOGLE_CLIENT_ID` and `GOOGLE_CLIENT_SECRET` environment variables and assign the OAuth client values we just created for each. 

You also need to include `NEXTAUTH_URL` (assign your app origin) and `NEXTAUTH_SECRET` environment variables in the `.env`.

When deploying to production, set the `NEXTAUTH_URL` environment variable to the canonical URL of your site.

Create a `NEXTAUTH_SECRET` environment variable for all environments. 
* You can use `openssl rand -base64 32` or https://generate-secret.vercel.app/32 to generate a random value. 
* You **do not** need the `NEXTAUTH_URL` environment variable in Vercel.

Your `.env.local` file should be looking like this when you're done.

```ts
// .env

GOOGLE_CLIENT_ID=YOUR_CLIENT_ID
GOOGLE_CLIENT_SECRET=YOUR_CLIENT_SECRET

NEXTAUTH_URL=http://localhost:3000
NEXTAUTH_SECRET=YOUR_SECRET
```
<br/>
<div>
<a href="https://github.com/pankod/refine">
  <img  src="https://refine.dev/img/github-support-banner.png" alt="github support banner" />
</a>
</div>



### For GithubProvider (you will need a GitHub account):

To create your GithubProvider ID and SECRET, navigate to your GitHub account [developer settings](https://github.com/settings/apps) and click on the OAuth Apps tab to register a new application.

![Github register](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/j6i13xz3wyelvj8urhad.png)


Complete application registration by filling out the fields.

![Github register enable](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8y0jenovdawpq4odmd0q.png)

Once completed, click on the "Register application" action button to register your app.
Remember to go back and change the URIs to your production URI once you push to production.

![Github secrets](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/s081q1q2wa44buvycklx.png)


Congratulations! You've just created your Github OAuth Client ID and SECRET. You can generate a new client secret by clicking on the "Generate a new client secret" action button.


Recall you've already created a `.env` file for your environment variables, go ahead and assign the Client ID and Client secrets you just generated to the `GITHUB_ID` and `GITHUB_SECRET` variables.



```ts
// .env
GOOGLE_CLIENT_ID=YOUR_CLIENT_ID
GOOGLE_CLIENT_SECRET=YOUR_CLIENT_SECRET

NEXTAUTH_URL=http://localhost:3000
NEXTAUTH_SECRET=YOUR_SECRET

GITHUB_ID=YOUR_ID
GITHUB_SECRET=YOUR_SECRET
```

This is the final look of our `.env` file.

Next, you will head into your `[...nextauth].js` file and add the secret, remember you've already added the environment variable as `NEXTAUTH_SECRET`. 


```ts
// pages/api/auth/[...nextauth].js

import NextAuth from "next-auth"
import GoogleProvider from "next-auth/providers/google";
import GithubProvider from "next-auth/providers/github"

export default NextAuth({
  // Configure one or more authentication providers
  providers: [
    GoogleProvider({
      clientId: process.env.GOOGLE_CLIENT_ID,
      clientSecret: process.env.GOOGLE_CLIENT_SECRET
    }),
    GithubProvider({
      clientId: process.env.GITHUB_ID,
      clientSecret: process.env.GITHUB_SECRET,
    }),
    // ...add more providers here
  ],
  secret: process.env.NEXTAUTH_SECRET
})
```

Congratulations! You’ve added your complete API route. The next thing you are going to do is to configure the shared session state.

## Configure Shared Session State

The `useSession()` React Hook in the NextAuth.js client is the easiest way to check if someone is signed in, and to be able to use this hook, first you’ll need to expose the session context, `<SessionProvider />`, at the top level of your application:



```ts 
// pages/_app.jsx

import { SessionProvider } from "next-auth/react"

export default function App({
  Component,
  pageProps: { session, ...pageProps },
}) {
  return (
    <SessionProvider session={session}>
      <Component {...pageProps} />
    </SessionProvider>
  )
}
```

Instances of `useSession` will then have access to the session data and status. The `<SessionProvider />` also takes care of keeping the session updated and synced between browser tabs and windows.

## Update Page Components
Now update the `pages/index.js` file to create a blog application. To that, add the code snippet below to the `page/index.js`.


```ts
// page/index.js

import Head from "next/head";
import Image from "next/image";
import styles from "../styles/Home.module.css";

export default function Home() {
  return (
    <div className={styles.container}>
      <Head>
        <title>Create Next App</title>
        <meta name="description" content="Generated by create next app" />
        <link rel="icon" href="/favicon.ico" />
      </Head>
      <main className={styles.main}>
        <h1 className={styles.title}>My Blog</h1>
        <div className={styles.row}>
          <div className={styles.blogCard}>
            <Image
              src="/Getting-Started-with-NextJS-Inside.jpeg"
              alt="blog1"
              width={300}
              height={200}
            />
            <div className={styles.blogCardContent}>
              <h2>Nexjs for Beginers</h2>
              <p>
                Lorem ipsum dolor sit amet consectetur adipisicing elit.
                Quisquam, quidem.
              </p>

              <a href="/blog1">Read More</a>
            </div>
          </div>
          <div className={styles.blogCard}>
            <Image
              src="/pasted image 0.png"
              alt="blog1"
              width={300}
              height={200}
            />
            <div className={styles.blogCardContent}>
              <h2>Django Full Course</h2>
              <p>
                Lorem ipsum dolor sit amet consectetur adipisicing elit.
                Quisquam, quidem.
              </p>

              <a href="/blog1">Read More</a>
            </div>
          </div>
        </div>
      </main>
    </div>
  );
}
```


Then add the code snippets in the `styles/Home.module.css` file to style the application.

```css
// styles/Home.module.css

.blogCard {
  margin: 1rem;
  padding: 1.5rem;
  text-align: left;
  color: inherit;
  text-decoration: none;
  border: 1px solid #eaeaea;
  border-radius: 10px;
  transition: color 0.15s ease, border-color 0.15s ease;
  max-width: 300px;
}
.blogCardContent {
  margin-top: 1rem;
}

.login {
  margin: 1rem;
  padding: 1.5rem;
  text-align: left;
  color: inherit;
  text-decoration: none;
  border: 1px solid #eaeaea;
  border-radius: 10px;
  transition: color 0.15s ease, border-color 0.15s ease;
  max-width: 300px;
}
.row {
  display: flex;
  flex-wrap: wrap;
  width: 100%;
  margin-right: -15px;
  margin-left: -15px;
  justify-content: center;
}
.header {
  display: flex;
  align-items: center;
}
.header button {
  margin-left: 10rem;
  padding: 4px;
  height: 2rem;
  background-color: #ad270c;
  border: none;
}
```

So if you refresh the application, you should see the blog application as shown in the screenshot below.


![Result view](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zrt5xnabj2h0kx197d7m.png)



Right now, everyone can have access to the application. Let's add a hook to restrict access to only authenticated users.

## Add React Hook
To know if a user is authenticated, we'll use the `useSession()` hook. To get started, we need to import and update the `pages/index.js` with the code snippet below.

```ts
// pages/index

import Head from "next/head";
import Image from "next/image";
import styles from "../styles/Home.module.css";
import { useSession, signIn, signOut } from "next-auth/react";

export default function Home() {
  const { data: session } = useSession();
  return (
    <div className={styles.container}>
      <Head>
        <title>Create Next App</title>
        <meta name="description" content="Generated by create next app" />
        <link rel="icon" href="/favicon.ico" />
      </Head>
      {!session ? (
        <>
          <p>Not signed in</p>
          <br />
          <button onClick={() => signIn()}>Sign in</button>
        </>
      ) : (
        <main className={styles.main}>
          <div className={styles.header}>
            <h4>Signed in as {session.user.name}</h4>
            <button onClick={() => signOut()}>Sign out</button>
          </div>
          <h1 className={styles.title}>My Blog</h1>
          <div className={styles.row}>
            <div className={styles.blogCard}>
              <Image
                src="/Getting-Started-with-NextJS-Inside.jpeg"
                alt="blog1"
                width={300}
                height={200}
              />
              <div className={styles.blogCardContent}>
                <h2>Nexjs for Beginers</h2>
                <p>
                  Lorem ipsum dolor sit amet consectetur adipisicing elit.
                  Quisquam, quidem.
                </p>

                <a href="/blog1">Read More</a>
              </div>
            </div>
            <div className={styles.blogCard}>
              <Image
                src="/pasted image 0.png"
                alt="blog1"
                width={300}
                height={200}
              />
              <div className={styles.blogCardContent}>
                <h2>Django Full Course</h2>
                <p>
                  Lorem ipsum dolor sit amet consectetur adipisicing elit.
                  Quisquam, quidem.
                </p>

                <a href="/blog1">Read More</a>
              </div>
            </div>
          </div>
        </main>
      )}
    </div>
  );
}
```

Let's point out what we did in the above code. First, we `NextAuth` hooks, the `useSession` which helps us know if a user is authenticated, the `signIn` hook to load the sign-in buttons and the `signOut` hook to log a user out. Then we destructured the `session` object from the `useSession` hook. The `session` object provides us with the information of the logged-in user. Using conditional rendering, we check if a user is logged in and render the blogs else show the user a sign-in button. 

Now, if you refresh the application, it will look like the screenshot below for non-authenticated users.

![Not sign in](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/e7l1xpuxdfoauer7nydf.png)


When the user clicks the sign-in button, they will be redirected to the sign-in button page as shown in the screenshot below.

![Sign in box](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jigs7qfozwbwyncmnwbw.png)



Now when they click on any of the buttons, they will be redirected to the  Google or Github page depending on which button they click. Once they are authenticated, the application will look like the screenshot below.


![Sign in result](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0nhhdqgr9kkq3oh4jo6h.png)


## Protect API Routes
NextAuth also allows you to protect your API routes. You can use the `unstable_getServerSession()` method to do that. Let's update and protect the `pages/api/hello.js` API with the code snippet below.

```ts
// pages/api/hello.js
// Next.js API route support: https://nextjs.org/docs/api-routes/introduction

import { unstable_getServerSession } from "next-auth/next"
import { authOptions } from "../api/auth/[...nextauth]"

export default async function handler(req, res) {
  const session = await unstable_getServerSession(req, res, authOptions)
  if (session) {
    const blogData = [
      {
        id: 1,
        title: "Blog 1",
        content: "Lorem ipsum dolor sit amet consectetur adipisicing elit. Quisquam, quidem.",
        image: "/images/blog1.jpg",
      },
      {
        id: 2,
        title: "Blog 2",
        content: "Lorem ipsum dolor sit amet consectetur adipisicing elit. Quisquam, quidem.",
        image: "/images/blog2.jpg",
      },
    ]
    res.status(200).json(blogData)
  } else {
    res.status(401).json({ message: "Unauthorized" })
  }
}
```
In the above code snippet, we imported the `unstable_getServerSession` method and the `authOptions` props. Then we created a `session` object from the `unstable_getServerSession` method passing in the `req`, `res` and `authOptions` as arguments. The session object will provide us with the details of the logged-in user. We check if a session exists and send the blog data to the client else send a `401` (Unauthorized) response.

## Conclusion
Throughout this tutorial, we've implemented how to add Google and GitHub authentication to a Nextjs application using NextAuth. We started by knowing what NextAuth is and why you should use it. Then we built a blog application for the demonstration. Now that you have the knowledge you seek, how would you add authentication to your next Nextjs project? Perhaps you can learn more about NextAuth from the [documentation](https://next-auth.js.org/).

Writer: Ekekenta Clinton

<br/>
<div>
<a href="https://discord.gg/refine">
  <img  src="https://refine.dev/img/discord-banner.png" alt="discord banner" />
</a>
</div>


## Build your React-based CRUD applications without constraints

Low-code React frameworks are great for gaining development speed but they often fall short of flexibility if you need extensive styling and customization for your project.

Check out [refine](https://github.com/pankod/refine), if you are interested in a headless framework you can use with any custom design or UI-Kit for 100% control over styling.

<div>
<a href="https://github.com/pankod/refine">
    <img  src="https://refine.dev/img/refine_blog_logo_1.png" alt="refine blog logo" />
</a>
</div>

<br/>

**refine** is a React-based framework for building CRUD applications **without constraints.**
It can speed up your development time up to **3X** without compromising freedom on **styling**, **customization** and **project workflow.**

**refine** is headless by design and it connects **30+** backend services out-of-the-box including custom REST and GraphQL API’s.

Visit [refine GitHub repository](https://github.com/pankod/refine) for more information, demos, tutorials and example projects.