4

I am a little bit confused about protected routes in next.js.

First of all, I don't want to use any server side rendering. I want to statically export via next export. In that case, how do I implement client side protected routes?

Say, I have a back-end server with basic JWT authentication. How do I make certain routes protected from certain user and redirect them in /login page?

fuadnafiz98
  • 450
  • 5
  • 15
  • Is this close to what you're trying to achieve? https://stackoverflow.com/questions/63251020/react-nextjs-protected-routes – Joel Hager Jun 10 '21 at 08:32
  • I may be wrong about my understanding but in the first answer, the author used `next-auth` and also used `/api`, I want just static export of my site like a typical create-react-app ie. without any server attached. I want to use my own backend server. – fuadnafiz98 Jun 10 '21 at 08:38

1 Answers1

6

Since you're wanting to create protected routes with a static export, you'll need to do everything in the browser.

  1. Verify their JWT in the browser
  2. If their JWT is valid, render the page (including all requests to fetch data)
  3. If their JWT is not valid, redirect them

For this, we're going to create a wrapper AuthCheck component.

Related:

How can you create a Private route in next.js?

AuthCheck

For verifying the JWT, you can use any method you'd like, including sending it to an api endpoint to verify it. Though I'm unsure if you can use Next.js api endpoints with static exports.

import { useRouter } from 'next/router'

export const AuthCheck = (props) => {
  const router = useRouter()
  const isJWTValid = useIsJWTValid() // you need to implement this. In this example, undefined means things are still loading, null means user is not signed in, anything truthy means they're signed in

  if (typeof window !== 'undefined' && user === null) router.push('/')

  if(!user) return <Loading /> // a loading component that prevents the page from rendering
   
  return props.children
}

You can then add this to your app.js.

const MyApp = ({ Component, pageProps }) => {
  return (
    <AuthCheck>
      <Component {...pageProps} />
    </AuthCheck>
  )
}

export default MyApp

Alternatively, you can also add this to any individual page. With this, you may need to debug the timing of any fetched data.

export default const ProtectedPage = () => {
  return (
    <AuthCheck>
      <!-- contents of the page -->
    </AuthCheck>
  )
}
Nick
  • 5,108
  • 2
  • 25
  • 58