Create Protected Routes In NextJS and NextAuth

nandkishoryadav

Nandkishor

Posted on December 7, 2021

Create Protected Routes In NextJS and NextAuth

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

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.

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>
}
Enter fullscreen mode Exit fullscreen mode

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.

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

Dashboard.auth = true
Enter fullscreen mode Exit fullscreen mode

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:

Dashboard.auth = {
  role: "admin",
  loading: <LoadingSkeleton />,
  unauthorized: "/login-with-different-user", // redirect to this url
}
Enter fullscreen mode Exit fullscreen mode

I hope this post helps.

💖 💪 🙅 🚩
nandkishoryadav
Nandkishor

Posted on December 7, 2021

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related