Implementing user authorization in Next.js
Tags: nextjs, webdev
Published: 2022-09-21 14:01:10

**Written by [Kingsley Ubah](https://blog.logrocket.com/author/kingsleyubah/)✏️**

The focus of this tutorial is on helping developers learn how to delegate the responsibilities of user authorization to some other service, such as GitHub or Google, rather than managing them in their application. We will cover:

*   [Authentication vs. authorization in Next.js](#authentication-vs-authorization-next-js)
*   [Introducing our user authorization project in Next.js](#user-authorization-project-next-js)
*   [Create a Next.js app](#create-next-js-app)
*   [Create a GitHub OAuth app](#create-github-oauth-app)
*   [Add API keys to environmental variables](#add-api-keys-environmental-variables)
*   [Install NextAuth.js and configure the GitHub provider](#install-nextauth-configure-github-provider)
*   [Access the user session with](#access-user-session-session-provider) [`<SessionProvider>`](#access-user-session-session-provider)
*   [Check the user login state with](#check-user-login-state-usesession) [`useSession()`](#check-user-login-state-usesession)
*   [Retrieve and display user information](#retrieve-display-user-information)
*   [Get additional scope data](#get-additional-scope-data)

## Authentication vs. authorization in Next.js <a name="authentication-vs-authorization-next-js">

Authentication is the act of validating that users are who they claim to be. Usernames and passwords are the most common authentication factors. 

[When authenticating a user](https://blog.logrocket.com/nextauth-js-for-next-js-client-side-authentication/), if the user enters the correct data, the server assumes the identity is valid and grants the user access to the server resource. 

On the other hand, authorization in a security system is the process of giving the user permission to access a specific resource or function on the server. This term is often used interchangeably with access control or client privilege. 

Usually, authentication precedes authorization; users should first prove their identities are genuine before the backend administrator grants them access to the requested resources.

## Introducing our user authorization project in Next.js <a name="user-authorization-project-next-js">

OAuth2.0 is an industry-standard authorization protocol that enables internet users to share their account information with third-party websites and applications without having to give out their account credentials. 

This guide uses the NextAuth.js library for user authorization (OAuth2.0) implementation in Next.js applications. 

[NextAuth.js is a full-fledged authentication and authorization solution](https://blog.logrocket.com/nextauth-js-for-next-js-client-side-authentication/) for Next.js designed to work with any OAuth service. It has built-in support for many popular sign-in services, including Google and GitHub. 

To follow this tutorial, you'll need [Node.js 12.0 or later](https://nodejs.org/en/download/) along with [basic knowledge of React](https://reactjs.org/tutorial/tutorial.html).

## Create a Next.js app <a name="create-next-js-app">

Let's begin by creating a new Next.js project. 

The following commands show how to create a new Next.js project using npm, Yarn, and pnpm respectively. Open up the terminal and run one of them:

```bash
npx create-next-app@latest
# or
yarn create next-app
# or
pnpm create next-app
```

You'll be prompted by the CLI to provide a name for your new project. Type your preferred name into the command prompt, then click `enter` on your keyboard to complete the installation. 

After installation is complete, run the following command to start the development server on your local machine:

```bash
npm run dev
# or 
yarn dev 
# or 
pnpm dev
```

This should start your dev server at port 3000 by default. Fire up your web browser and navigate to http://localhost:3000\. You should see the Next.js starter page as is shown below. ![Next Js Starter Page Shown When Opened In Browser At Localhost 3000 With Welcome Message And Links To Documentation, Course, Examples, And Vercel Deployment](https://blog.logrocket.com/wp-content/uploads/2022/09/img1-Next-js-starter-page-browser.png) 

Next, you'll create a new OAuth app on GitHub to register your application with OAuth.

## Create a GitHub OAuth app <a name="create-github-oauth-app">

We want users to sign in with their GitHub account and authorize our app to access certain information from their account. 

To do this, we need to first [create a new GitHub OAuth App](https://github.com/settings/developers). Click on “New OAuth app” and fill out the form accordingly with your website information. Here are some important things to note about the information requested by the form:

*   In the “Application name” field, type the name of your app (for example, “My App”)
*   In the “Homepage URL” field, type the full URL to your website's homepage
    *   Since we're in development mode, it is: `http://localhost:3000`
*   In the “Authorization callback URL” field, type the callback URL of your app

The authorization callback URL is the URL you want GitHub to redirect to after the user has authorized your app. It should be your homepage URL plus `/api/auth/callback`. 

In this case, the full URL should be `http://localhost:3000/api/auth/callback`. 

The other fields are not really important; as such, they can be left blank. 

After registering the GitHub app, you'll be moved to a page containing your OAuth Client ID. Click “Generate a new secret key” to generate a Client Secret key as well. 

Preserve both keys for the next step.

## Add API keys to environmental variables <a name="add-api-keys-environmental-variables">

Next.js comes with built-in support for environment variables. To use them in your project, create a file named `.env.local` in the root of your project directory:

```bash
touch .env
```

Open `.env.local` and add the following:

```javascript
GITHUB_ID=<your-client-id>
GITHUB_SECRET=<your-client-secret>
NEXTAUTH_URL=http://localhost:3000
```

Replace the above templates with your actual values from GitHub.

## Install NextAuth.js and configure the GitHub provider <a name="install-nextauth-configure-github-provider">

Now that you've created an OAuth application on GitHub, it's time to set up the front-end application. 

First, install NextAuth.js by running the following command:

```bash
npm install next-auth --save
```

With the library installed, you must now create a file named `[...nextauth].js` in `pages/api/auth`. This file will contain all the providers that you want to use in your app. Each provider will be configured using the credentials in order for the app to successfully connect with our OAuth identity provider. 

Since we registered with GitHub, we'll use just the GitHub provider. Add the following code in the newly created `[...nextauth].js` file:

```javascript
import NextAuth from 'next-auth'
import GitHubProvider from "next-auth/providers/github";

const options = {
    providers: [
        GitHubProvider({
            clientId: process.env.GITHUB_ID,
            clientSecret: process.env.GITHUB_SECRET
        }),
    ],
}

export default (req, res) => NextAuth(req, res, options)
```

First, we imported `NextAuth` and `GitHubProvider`. Then we configured `GitHubProvider` with our `GITHUB_ID` and `GITHUB_SECRET` environmental variables, retrieved from `process.env`. 

The last line exports a function that returns the `NextAuth` and takes the `options` variable as a third parameter. 

That's all we need to connect our app with GitHub! 

To see this in effect, run your dev server with `npm run dev`. Using the REST API provided by next-auth, you can sign into the app with your GitHub account. Navigate to http://localhost:3000/api/auth/signin and you should see the below: 

![Button Prompt To Sign Into Web App With Github Account](https://blog.logrocket.com/wp-content/uploads/2022/09/img2-Sign-in-with-GitHub-button.png) 

Click on the button and you'll be led to the GitHub consent page telling you to authorize the app. If you do, you'll be signed in with GitHub. However, the app will not reflect that you're signed in because we have yet to get the user session data in the app. Let's tackle that next!

## Access the user session with `<SessionProvider>` <a name="access-user-session-session-provider">

When the user authorizes our app, you need to show the user that they are signed in by rendering the user details on the front end of our app. In order for any of this to work, we must first [wrap our entire app with](https://next-auth.js.org/getting-started/client#sessionprovider) [`<SessionProvider>`](https://next-auth.js.org/getting-started/client#sessionprovider). 

Create an `_app.js` file in your pages directory (if it doesn’t already exist) and add the following code:

```javascript
import { SessionProvider } from "next-auth/react"
import '../styles/globals.css'

function MyApp({ Component, pageProps }) {
  return (
    <SessionProvider session={pageProps.session}>
      <Component {...pageProps} />
    </SessionProvider>
  )
}

export default MyApp
```

With this code, all the pages within the app will have access to the user session, and this session will be preserved during site navigation. The session will also be shared with the OAuth provider. That way, the app doesn't re-authenticate the user every time he or she visits the site.

## Check the user login state with `useSession()` <a name="check-user-login-state-usesession">

The `useSession()` hook allows us to check the login state of the user and retrieve the user's session information. We'll use this hook along with `signIn` and `signOut` to implement a `<Header>` component that checks if the user is authenticated and renders either a "Sign in" or "Sign out" link. 

Open the `components/Header.js` file and import `useSession`, `signIn`, and `signOut` from [the NextAuth.js client library](https://next-auth.js.org/getting-started/client):

```javascript
import { useSession, signIn, signOut } from 'next-auth/react'
```

`signIn` and `signOut` will be used to log users in and out of our app. We need to create the `handleSignin` and `handleSignout` methods to trigger both functionalities:

```javascript
const handleSignin = (e) => {
      e.preventDefault()
      signIn()
  }    
const handleSignout = (e) => {
      e.preventDefault()
      signOut()
    }
```

Next, let's retrieve the user’s session data:

```javascript
const { data: session } = useSession();
```

Once the data is retrieved, it can then be displayed to users on the page or manipulated with JavaScript. Let’s use the returned details to conditionally render a sign-in and sign-out button. 

Replace everything in the return statement in `components/Header.js` with the following code:

```javascript
<div className='header'>
      <Link href='/'>
        <a className='logo'>NextAuth.js</a>
      </Link>
           {session && <a href="#" onClick={handleSignout} className="btn-signin">Sign out</a>  } 
           {!session && <a href="#" onClick={handleSignin}  className="btn-signin">Sign in</a>  } 
    </div>
```

Your `Header.js` file should now look like this:

```javascript
import { useSession, signIn, signOut } from 'next-auth/react'
import Link from 'next/link'

export default function Header() {  
    const handleSignin = (e) => {
        e.preventDefault()
        signIn()
    }

    const handleSignout = (e) => {
        e.preventDefault()
        signOut()
    }

    const { data: session } = useSession();

    return (
      <div className='header'>
        <Link href='/'>
          <a className='logo'>AppLogo</a>
        </Link>
             {session && <a href="#" onClick={handleSignout} className="btn-signin">SIGN OUT</a>  } 
             {!session && <a href="#" onClick={handleSignin}  className="btn-signin">SIGN IN</a>  } 
      </div>

    )
  }
```

Next, we'll retrieve the user information and display it to the user upon authorizing our app.

## Retrieve and display user information <a name="retrieve-display-user-information">

Inside our `pages/index.js` file, we need to display and conditionally render the user details based on their authentication status. 

If the user is logged in, we will render their profile image, name, and photo using the data from our session state. The user will be authorized to view or interact with all app pages, as well as to log out. 

If the user is not logged in, we will render a dummy user profile image and text instructing them to log in and authorize the app to access their GitHub profile information. The user will not be authorized to view or interact with any other part of the app. 

To do this, replace your `index.js` file content with the following:

```javascript
import Head from 'next/head
import Header from '../components/Header'
import styles from '../styles/Home.module.css'
import { useSession } from 'next-auth/react'

export default function Home() {
  const { data: session, status } = useSession()
  const loading = status === "loading"

  return (
    <div className={styles.container}>
      <Head>
        <title>Nextjs | Next-Auth</title>
        <link rel="icon" href="/favicon.ico" />
      </Head>
      <Header />
      <main className={styles.main}>        
        <div className={styles.user}>
           {loading && <div className={styles.title}>Loading...</div>}
           {
            session &&
              <>
                <h1 className={styles.title}>Welcome, {session.user.name ?? session.user.email}!</h1>
               <p style={{ marginBottom: '10px' }}> </p> <br />
               <img src={session.user.image} alt="" className={styles.avatar} />
              </>
            }
           {
            !session &&
              <>
               <p className={styles.title}>Please log in to continue</p>
               <img src="no-user.jpg" alt="" className={styles.avatar} />               
              </>
           }
         </div>
      </main>
    </div>
  )
}
```

Here's the page when I’m logged out: ![Web App Page Showing Dummy User Profile Image And Login Instruction Text When User Is Not Logged In](https://blog.logrocket.com/wp-content/uploads/2022/09/img3-Page-when-logged-out.png) 

And here's the page when I'm logged in with my GitHub account: ![Web App Page Showing User Details When User Is Signed In With Github](https://blog.logrocket.com/wp-content/uploads/2022/09/img4-Page-when-logged-in.png) 

Feel free to [grab the complete source code on GitHub](https://github.com/KingsleyUbah/next-auth-google)!

## Get additional scope data <a name="get-additional-scope-data">

Note that the default scope for the GitHub OAuth Provider is `read:users`, which authorizes your application to read the user's profile data, such as name, email, and profile picture. 

In order to get data from scopes other than the default ones, you'll need to define the scopes in your Provider's configuration object inside the `pages/api/auth/[...nextauth].js` directory. 

For example, let's request permission to read the user's notifications in addition to their profile data by adding the `authorization.params.scope` property to `GitHubProvider`:

```javascript
// imports

const options = {
    providers: [
        GitHubProvider({
            clientId: process.env.GITHUB_ID,
            clientSecret: process.env.GITHUB_SECRET,
            // add this:                     
            authorization: { params: { scope: 'notifications' } },
        }),
    ],
}

// export 
```

Navigate to http://localhost:3000 on your browser and try signing in with the same GitHub account. You should get the following. ![User Prompt To Grant Additional Permissions Authorizing App To Read User Notifications With Information About What Access Is Granted And Buttons To Cancel Or Grant Authorization](https://blog.logrocket.com/wp-content/uploads/2022/09/img5-Authorization-page-request-permissions.png) 

See the [full list of available GitHub OAuth scopes](https://docs.github.com/en/developers/apps/building-oauth-apps/scopes-for-oauth-apps). 

To learn more about NextAuth.js, including how to use callbacks, [JWT tokens](https://blog.logrocket.com/jwt-authentication-best-practices/), events, and other advanced configuration options, feel free to read the [NextAuth.js documentation](https://next-auth.js.org/getting-started/introduction).

## Conclusion

Using the NextAuth.js library, you should now be able to configure a Next.js application to use the OAuth flow for user authorization. The NextAuth.js library provides built-in support for many popular sign-in services, making the process of API integration quick and easy. 

You can [get the source code from this GitHub repository](https://github.com/KingsleyUbah/next-auth-google). If you have any questions related to this topic, please let me know in the comments.