How to implement protected routes in Next.js

One of the features that is neccessary in a single page application as it pertains to the authentication or its security is the ability to conditionally show some UI to the users based on their authentication state.

In this article, you’re going to le…


This content originally appeared on DEV Community and was authored by DEV Community

One of the features that is neccessary in a single page application as it pertains to the authentication or its security is the ability to conditionally show some UI to the users based on their authentication state.

In this article, you’re going to learn how to implement this fetaure in a Next.js application, as you do not want an unauthorized user getting access to private user inerfaces like the dashboard unless they’re currently authenticated.

But, before you read this article any further, you should have an idea of the following:

  • Conditional rendering in React
  • localStorage and its basic methods
  • The basics of the React Context API

Setting up a Next.js App

We’ll be focusing on using Next.js in this article. So Let us creating a Next.js app by typing command below into our terminal

npx create-next-app [name-of-your-app]

Let us have a look at the file structure of the app below. We’ll focus on the important files that we need in this app, so it’ll be concise.

     |--pages
     |   |-- api
     |   |-- _app.js
     |   |-- index.js (dashboard page)
     |--src
     |   |-- context
     |   |     |-- auth-context.js
     |   |__
     |__ 

The pages directory is where all the routing of the app takes place. This is an out-of-the-box feature of Nextjs. It saves you the stress of hard-coding your independent routes.

pages/_app.js: is where all our components get attached to the DOM. If you take a look at the component structure, you’ll see that all the components are passed as pageProps to the Component props too.

npm run dev

Setting up the authContext

In the previous section, we saw the basic structure of a Next.js app and the function of the files that
we’ll be interacting with, in this article.

Let’s start by moving into the context folder where we have the auth-context.js file. This file, with the help of React’s Context API, helps us store the authentication state of our application. You can read more about the context API here if it is new to you.

// src/context/auth-context.js
import React from "react";
import { useRouter } from "next/router";

const AuthContext = React.createContext();
const { Provider } = AuthContext;

const AuthProvider = ({ children }) => {
  const [authState, setAuthState] = React.useState({
   token: "",
  });

  const setUserAuthInfo = ({ data }) => {
   const token = localStorage.setItem("token", data.data);

   setAuthState({
    token,
   });
 };

 // checks if the user is authenticated or not
 const isUserAuthenticated = () => {
  if (!authState.token) {
    return false;
  }
 };

 return (
   <Provider
     value={{
      authState,
      setAuthState: (userAuthInfo) => setUserAuthInfo(userAuthInfo),
      isUserAuthenticated,
    }}
   >
    {children}
   </Provider>
 );
};

export { AuthContext, AuthProvider };

The snippet above contains all that we need to have a preserved auth-state in our application. But, let us break it down into smaller chunks and understand what it does.

You’d notice that we’re making use of the useState hook in React to define the initial value of our authentication state authState and the data type that we assigned to it as an object.

const [authState, setAuthState] = React.useState({
 token: "",
});

Why? You’d ask. Well, it is so that we can factor multiple states in our application. Say, for example, we have other states that needs to be preserved, asides the user’s auth-state, all we’d do is add another property to the authState object.

Now, we need a way to properly store the unique JWT (JSON Web Token) that is assigned to any user when they originally signed up on our app. This is where we employ the use of the browser’s localStorage API

const setUserAuthInfo = ({ data }) => {
 const token = localStorage.setItem("token", data.data);

 setAuthState({
  token,
 });
};

What we did in the snippet above was to store the user token in localStorage and also look for a way to make the value of the token to be available in the app state, by using the setAuthState setter function that we declared in the useState hook.

All we have done up until this moment is store the user info (i.e the token). The next step is to check if there’s any JWToken in the browser’s localStorage when the page is first mounted.

const isUserAuthenticated = () => {
 if (!authState.token) {
  return false;
 }
};

The snippet above checks for the token. If the token is not in localStorage, it returns false. If it is, it returns true.

These functions are, in turn, passed as values to the value prop in the Provider

<Provider
 value={{
  authState,
  setAuthState: (userAuthInfo) => 
  setUserAuthInfo(userAuthInfo),
  isUserAuthenticated,
 }}
/>

Using authContext in the dashboard page

The authContext from the previous section can now be imported into the dashboard page, and we can make use of the isUserAuthenticated prop in the authContext Provider to check if the user is already authenticated.

// pages/dashboard
export default function Dashboard() {
  const router = useRouter();
  const authContext = React.useContext(AuthContext);

  React.useEffect(() => {
   // checks if the user is authenticated
   authContext.isUserAuthenticated()
   ? router.push("/")
   : router.push("/dashboard");
  }, []);

  return (
   <React.Fragment>
    <Head>
     <title>Dashboard</title>
    </Head>
    <div>
     <h2>Dashboard</h2>
    </div>
   </React.Fragment>
 );
}

For this to work, the conditional statement has to be in the useEffect hook of React.js. Since the hook runs on every new render of the component (which is our dashboard page).

So anytime a user manually goes to the dashboard route, without logging in first, they get sent back to the home page or the login page.

React.useEffect(() => {
  // checks if the user is authenticated
  authContext.isUserAuthenticated()
  ? router.push("/")
  : router.push("/dashboard");
}, []);

In the snippet above you’ll see that we made use of Next.js’ useRouter module to get access to the app’s route. Remember how the isUserAuthenticated function will always return false in the authContext.

So now, in this scenario, if the token isn’t in localStorage the user will always get sent to the login route or at least the homepage.

Conclusion

If you have a lot of routes in your application that you don't want to be accessible to users that are not authenticated, all you have to do is repeat the process in these individual routes.

Thank you for reading this article, I hope it has helped you understand how to implement protected routes in Next.js.


This content originally appeared on DEV Community and was authored by DEV Community


Print Share Comment Cite Upload Translate Updates
APA

DEV Community | Sciencx (2022-03-05T15:35:26+00:00) How to implement protected routes in Next.js. Retrieved from https://www.scien.cx/2022/03/05/how-to-implement-protected-routes-in-next-js/

MLA
" » How to implement protected routes in Next.js." DEV Community | Sciencx - Saturday March 5, 2022, https://www.scien.cx/2022/03/05/how-to-implement-protected-routes-in-next-js/
HARVARD
DEV Community | Sciencx Saturday March 5, 2022 » How to implement protected routes in Next.js., viewed ,<https://www.scien.cx/2022/03/05/how-to-implement-protected-routes-in-next-js/>
VANCOUVER
DEV Community | Sciencx - » How to implement protected routes in Next.js. [Internet]. [Accessed ]. Available from: https://www.scien.cx/2022/03/05/how-to-implement-protected-routes-in-next-js/
CHICAGO
" » How to implement protected routes in Next.js." DEV Community | Sciencx - Accessed . https://www.scien.cx/2022/03/05/how-to-implement-protected-routes-in-next-js/
IEEE
" » How to implement protected routes in Next.js." DEV Community | Sciencx [Online]. Available: https://www.scien.cx/2022/03/05/how-to-implement-protected-routes-in-next-js/. [Accessed: ]
rf:citation
» How to implement protected routes in Next.js | DEV Community | Sciencx | https://www.scien.cx/2022/03/05/how-to-implement-protected-routes-in-next-js/ |

Please log in to upload a file.




There are no updates yet.
Click the Upload button above to add an update.

You must be logged in to translate posts. Please log in or register.