How to create private routes with nextJs

Asked

Viewed 893 times

1

Hello, I would like a help for creating private routes using Nextjs. All files deposited inside the directory pages become accessible routes, in my application some of these must be accessible when the user is logged in. I am currently using useEffect to check if there is an object called username in the sessionStorage, the code below is on the login page and redirects the user if it is already connected:

useEffect(() => {
  const session = sessionStorage.getItem('username');
  if (session) {
    router.push(router.query.followPage || '/');
  }
}, [router]);

This method is far from efficient, and redirects the user after the page’s initial load showing the user screen components, as well as being slower at redirecting. Similar validations exist on other pages, in these if username does not exist the user is directed to login page.

I found some instructions for creating a HOC (Higher-Order Component) and involving my private pages with it, that sounds promising but I could not understand how the author proposes that user data be validated, that is, how the user session is verified by the function created by it checkUserAuthentication at this source: https://medium.com/@eslamifard.ali/how-to-Simply-create-a-private-route-in-next-js-38cab204a99c

Use the function getInitialProps next to check the server-side user authentication and redirect it from there seems efficient, I found some sources suggesting to pass a token in the request header but again, I didn’t understand how this works if the user goes to the page directly through the url without using some internal link of the page.

So what’s the best way to create private routes with Nextjs?

  • The current application I am developing is very simple and does not need large levels of security, a simple validation on the user session is already enough for my case, a response that uses a validation based on the sessionStorage will already be welcome, but if you want to contribute a more advanced response for future users looking for it, feel free.

  • Just a question to ask... In this scenario (where the user has to be logged in to view the page) is it really worth using Next? The main purpose of Next is to allow SSR (and similar) to improve SEO. But if the page is private, this is not necessary. Anyway, I’m not saying stop using Next, but it’s something to think about. Authentication with Next is not very trivial to do because you have to synchronize the token authorization between client and server, which can take a little work.

  • It’s a great question, I didn’t make it clear in the question but I’m extending an existing application, deal with a site that was built in next and that now the client wants to include two pages that only he has access to, there is no really private information in them, but the client does not want to expose the same for now.

1 answer

1


The answer was right in front of me the whole time, sessionStorage and localStorage cannot be accessed in the functions executed on the server, but cookies can, so the solution if you want to create a private route as a simple authentication is to save your session in cookies. I used the lib js-cookies to manipulate my application’s cookies but this is optional. The example below demonstrates how to save the cookie to the system:

import cookie from 'js-cookie';

function signIn(email, password) {
  // aqui é sua validação no servidor
  cookie.set('nomeDoCookie', 'valorDoCookie', { expires: 1, path: '/' });
  // você pode incluir um redirecionamento aqui se quiser
}

Now on the page you want to make private, export the function getServerSideProps as shown below:

export async function getServerSideProps(ctx) {
  const isAuthenticated = (req) => {
    if (!req?.headers?.cookie) {
      return undefined;
    }

    const match = req.headers.cookie
      .split(';')
      .find((item) => item.trim().startsWith('nomeDoCookie='));

    if (!match) {
      return undefined;
    }

    return match.split('=')[1];
  };

  if (!isAuthenticated(ctx.req)) {
    ctx.res.writeHead(303, { Location: 'paginaDeLogin' });
    ctx.res.end();
  }

  return { props: {} };
}

Of course you must create the function isAuthenticated in a separate file and just call it where you need it. This is a simple way to make a private route using cookies, you can also use the function getInitialProps to validate cookies, but it is not advisable because it makes the code more complex since it is necessary to make validations to know if the execution is happening on the server or client

getServerSideProps is very similar to getInitialProps, meaning that it gets called Every time that you load the page, but the code is only executed on the server.

Source: https://www.datocms.com/blog/how-the-new-next-js-9-3-preview-mode-works

It is important to note that in this example I am just checking if the cookie exists, I am not checking whether it is valid or not, in my case this is enough, but maybe you want to check some more secure verification examples, search for auth on the nextJs examples page to find out some ways to authenticate. https://github.com/vercel/next.js/tree/canary/examples

This article was useful to me while I was researching ways to do what I needed: https://medium.com/@positivecarlos/Authentication-on-universal-React-with-next-js-b441ef458046

Browser other questions tagged

You are not signed in. Login or sign up in order to post.