NextJS app temporarily shows restricted route component

Viewed 92

I am trying to globally protect all routes that include 'dashboard' in the pathname but when I type '/dashboard' it shows the components for about 1 second and only then redirects to /login

How can I redirect users to /login before the /dashboard component loads? I don't want unauthenticated users to see the component.

export const AuthContextProvider: FC<Props> = ({ children }) => {
  const [admin, setAdmin] = useState<Partial<Admin>>(null);
  const router = useRouter();
  const { loading } = useCurrentAdminQuery({
    onCompleted: (data) => {
      setAdmin(data.currentAdmin);
    },
    onError: () => {
      if (router.pathname.includes('dashboard'))
        return router.replace('/login');
    },
    fetchPolicy: 'network-only',
  });

  if (loading) return <div>loading...</div>;

  return (
    <AuthContext.Provider value={{ admin, setAdmin }}>
      {children}
    </AuthContext.Provider>
  );
};
1 Answers

Providers are browser ReactJS features, not server-side features. You need a server-side version for your use-case.

For example each Page object should server side test your authentication rules.

const MyPage = () => (
 <div> This is protected content </div>  
)

export async function getServerSideProps() {
  // test your authentication logic here
  
  // Redirect when not logged-in
  return {
     redirect: {
        destination: '/login',
        permanent: false,
     },
  };

  // If all went well, pass some props, like username
  return { props: { username: 'john' } }
}

Or you can read the chapter about NextJS authentication. There is a useUser hook which you can use, which will redirect you to the login page.

I don't think there is an easy solution to "protect" some url prefix using NextJs yet. You could create a custom server, but it's a bit advanced, and there are downsides, which are described in the documentation, https://nextjs.org/docs/advanced-features/custom-server

Related