Create Protected Routes In NextJS and NextAuth
Tags: nextjs, nextauth
Published: 2021-12-07 19:53:10

Protecting Routes from unauthenticated users is a crucial part of any app.

In this article, I'll show you exactly how to create protected routes in your NextJS application using NextAuth.

I'll use a JWT token as an example, with the **accessToken**  being saved in the session. Check this article for more information.
[How to implement NextAuth credentials provider with external API and login page](https://cloudcoders.xyz/blog/nextauth-credentials-provider-with-external-api-and-login-page/)

Because of the way Next.js handles **getServerSideProps** and **getInitialProps**, every protected page load must make a server-side request to determine whether the session is valid before generating the requested page (SSR). This increases server load, but there is an option if you are comfortable making requests from the client. You can use **useSession **to ensure that you always have a valid session. If no session is identified after the initial loading state, you can determine the appropriate action to take.

First, let's modify our **_app.js** file.

```javascript
import { SessionProvider, useSession, signIn } from 'next-auth/react';
export default function App({
  Component,
  pageProps: { session, ...pageProps },
}) {
  return (
    <SessionProvider session={session}>
      {Component.auth ? (
        <Auth>
          <Component {...pageProps} />
        </Auth>
      ) : (
        <Component {...pageProps} />
      )}
    </SessionProvider>
  )
}

function Auth({ children }) {
  const { data: session, status } = useSession()
  const isUser = !!session?.user
  React.useEffect(() => {
    if (status === "loading") return
    if (!isUser) signIn()
  }, [isUser, status])

  if (isUser) {
    return children
  }

  // Session is being fetched, or no user.
  // If no user, useEffect() will redirect.
  return <div>Loading...</div>
}
```
Line #23: Do nothing while in the loading state.

Line #24: If the user is not authenticated, force the user to the login page.

## Custom Client Session Handling
Because of how Next.js handles **getServerSideProps** / **getInitialProps**, every protected page load must make a server-side request to determine whether the session is valid and then build the requested page. This alternate technique enables for the display of a loading status on the initial check, and all subsequent page transitions will be client-side, eliminating the need to check with the server and regenerate pages.

Consider the "/dashboard" page. Only authorized users should be able to view this page.

```javascript
export default function Dashboard() {
  const { data: session } = useSession()
  return "Some super secret dashboard"
}

Dashboard.auth = true
```
The session is always non-null inside this page, all the way down the React tree.

Notice that we are using **Dashboard.auth = true** to check if the user is authenticated, if not redirect to the login page.

We need to add **auth = true** to every page that we want to protect from the unauthenticated user.

It is simple to extend/modify to support something similar to an options object for role-based authentication on pages. As an example:
```javascript
Dashboard.auth = {
  role: "admin",
  loading: <LoadingSkeleton />,
  unauthorized: "/login-with-different-user", // redirect to this url
}
```
I hope this post helps.