1
\$\begingroup\$

I have a simple project that I built that protects the routes/pages of the website by using the if and else statement and putting each page with a function withAuth(), but I'm not sure if that is the best way to protect routes with nextjs, and I noticed that there is a delay in protecting the route or pages, like 2-3 seconds long, in which they can see the content of the page before it redirects the visitor or unregistered user to the login page.

Is there a way to get rid of it or make the request faster so that unregistered users don't view the page's content? Is there a better approach to safeguard a certain route in the nextjs framework?

Code


import { useContext, useEffect } from "react";
import { AuthContext } from "@context/auth";
import Router from "next/router";

const withAuth = (Component) => {
  const Auth = (props) => {
    const { user } = useContext(AuthContext);

    useEffect(() => {
      if (!user) Router.push("/login");
    });

    return <Component {...props} />;
  };

  return Auth;
};

export default withAuth;

Sample of the use of withAuth

import React from "react";
import withAuth from "./withAuth";

function sample() {
  return <div>This is a protected page</div>;
}

export default withAuth(sample);
\$\endgroup\$
2
  • 1
    \$\begingroup\$ Hello, welcome to CR! This code looks like a stub, which is great for StackOverflow, but not great for CodeReview. There really isn't enough to work with (what you have looks good). \$\endgroup\$
    – konijn
    Nov 25, 2021 at 9:20
  • \$\begingroup\$ Does or doesn't, to the best of your knowledge, the code presented work as needed? \$\endgroup\$
    – greybeard
    Nov 26, 2021 at 3:55

1 Answer 1

3
\$\begingroup\$

Obviously AuthContext from @context/auth is a blackbox to me here, so I'm unable to know if there's a server side auth capability. However, if you're able to retrieve the session server side, then with Next.js, you can use getServerSideProps to redirect to /login if there's no user found. This would prevent the user from seeing any protected content on the page as you mentioned.

For example:

// pages/myPage.js

import { getUser } from "@context/auth";

export async function getServerSideProps(context) {
  const { user } = await getUser();

  if (!user) {
    return {
      redirect: {
        destination: "/login",
        permanent: false,
      },
    };
  }

  return {
    props: { user },
  };
}

const MyPage = ({ user }) => {
  return <div>This is a protected page</div>;
};

export default MyPage;

In general, on the client side (if you're unable to do this server side), I think that avoiding a higher order component pattern will improve readability. I'd create a simple composition instead, something like this:

import { useContext, useEffect, useState } from "react";
import { AuthContext } from "@context/auth";
import Router from "next/router";

const Authorised = ({ children }) => {
  const { user } = useContext(AuthContext);

  useEffect(() => {
    if (!user) Router.push("/login");
  }, [user]);

  if (!user) {
    return null;
  }

  return children;
};

const Sample = () => {
  <Authorised>
    <div>This is protected content</div>
  </Authorised>
};

Due to the fact you mentioned a delay (before the redirect?), I'd suggest you render a loading component, rather than null, for a better user experience, until you have retrieved the user session.

I think it's also worth you reading the docs from Next.js on authentication, if you haven't done so already.

\$\endgroup\$
0

Not the answer you're looking for? Browse other questions tagged or ask your own question.