How to allow redirect in Next.js only after reCaptcha

Viewed 356

I have a Next.js app, index page contains only captcha, and after successfull entry redirects to form at mydomain.com/form and that works just fine. But also i can just enter in browser

mydomain.com/form

and get to it without captcha, which i obviously dont want.

Is there a way to restrict all entries except redirect from captcha page? Found only solutions with logins, e.t.c which i dont need.

Im using react-google-recaptcha package

Here is my index page

function Captcha() {
  const reRef = useRef<ReCAPTCHA>(null);
  const router = useRouter()
  return (
    <div className={styles.container}>
      <h1>Подтвердите, что вы не робот</h1>
      <ReCAPTCHA
        sitekey={`${process.env.NEXT_PUBLIC_RECAPTCHA_SITE_KEY}`}
        size="normal"
        ref={reRef}
        onChange={() => router.push('/form')}
      />
    </div>
  );
}
2 Answers

The logic is same with that of authorizing restricted page based on authentication context.

In this case, create a Context Provider that contains the state whether reCaptcha validation has been done. Then use useContext in your form component to either render or redirect based on the state provided by the reCaptcha context

Solved it using this guide.

TL:DR Basically im adding a token to local storage after successful captcha, token is necessary to access form page.

Created a HOC named withAuth

import { useRouter } from "next/router";
const withAuth = (WrappedComponent: any) => {
  return (props: JSX.IntrinsicAttributes) => {
    // checks whether we are on client / browser or server.
    if (typeof window !== "undefined") {
      const Router = useRouter();

      const accessToken = localStorage.getItem("accessToken");

      // If there is no access token we redirect to "/" page.
      if (!accessToken) {
        Router.replace("/");
        return null;
      }

      // If this is an accessToken we just render the component that was passed with all its props

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

    // If we are on server, return null
    return null;
  };
};



export default withAuth;

Changed captcha page to clean local storage on every load and put a token in after successful entry.

    function Captcha() {
  const reRef = useRef<ReCAPTCHA>(null);
  const router = useRouter()
  if(process.browser){localStorage.clear()}
  
  return (
    <div className={styles.container}>
      <h1>Подтвердите, что вы не робот</h1>
      <ReCAPTCHA
        sitekey={`${process.env.NEXT_PUBLIC_RECAPTCHA_SITE_KEY}`}
        size="normal"
        ref={reRef}
        onChange={() => 
          {
            localStorage.setItem("accessToken" , "1"),
            router.push('/form')
          }
        }
      />
    </div>
  );
}

export default Captcha;

And passed my form component to withAuth (changed from export default Home)

export default withAuth(Home);
Related