TransWikia.com

React and reCAPTCHA v3

Stack Overflow Asked by ComCool on December 3, 2020

Is there any easy way to use reCAPTCHA v3 in react? Did a google search an can only find components for v2. And only react-recaptcha-v3 for v3.

But I get an error Invalid site key or not loaded in api.js when I try to use the component.

3 Answers

I am teaching myself React + TypeScript and this is what I came up with to implement recaptcha v3.

I wanted a simple solution that would allow me to:

  • get the token dynamically only when the form is submitted to avoid timeouts and duplicate token errors
  • use recaptcha only on some components for privacy reasons (eg. login, register, forgot-password) instead of globally defining recaptcha api.js in index.html
  • require the least code possible to implement in a component

reCAPTCHA.ts

declare global {
    interface Window {
        grecaptcha: any;
    }
}

export default class reCAPTCHA {
    siteKey: string;
    action: string;

    constructor(siteKey: string, action: string) {
        loadReCaptcha(siteKey);
        this.siteKey = siteKey;
        this.action = action;
    }

    async getToken(): Promise<string> {
        let token = "";
        await window.grecaptcha.execute(this.siteKey, {action: this.action})
            .then((res: string) => {
                token = res;
            })
        return token;
    }
}

const loadReCaptcha = (siteKey: string) => {
    const script = document.createElement('script')
    script.src = `https://www.recaptcha.net/recaptcha/api.js?render=${siteKey}`
    document.body.appendChild(script)
}

To use this class declare it as a property in the component:

recaptcha = new reCAPTCHA((process.env.REACT_APP_RECAPTCHA_SITE_KEY!), "login");

And on form submit get the token that you need to pass to backend:

let token: string = await this.recaptcha.getToken();

To verify the token on the backend:

recaptcha.ts

const fetch = require("node-fetch");
const threshold = 0.6;

export async function validateRecaptcha(recaptchaToken: string, expectedAction: string) : Promise<boolean> {
    const recaptchaSecret = process.env.RECAPTCHA_SECRET_KEY;
    const url = `https://www.recaptcha.net/recaptcha/api/siteverify?secret=${recaptchaSecret}&response=${recaptchaToken}`;
    let valid = false;
    await fetch(url, {method: 'post'})
        .then((response: { json: () => any; }) => response.json())
        .then((data: any)=> {
            valid = (data.success && data.score && data.action && data.score >= threshold && data.action === expectedAction);
        });
    return valid;
}

I have very limited experience with JS/TS and React but this solution does work for me. I welcome any input on improving this code.

Answered by HomeIsWhereThePcIs on December 3, 2020

Hey you don't need a package, its just an unnecessary package you don't need. https://medium.com/@alexjamesdunlop/unnecessary-packages-b3623219d86 I wrote an article about why you shouldn't use it and another package. Don't rely on some package! Rely on google instead :)

const handleLoaded = _ => {
  window.grecaptcha.ready(_ => {
    window.grecaptcha
      .execute("_reCAPTCHA_site_key_", { action: "homepage" })
      .then(token => {
        // ...
      })
  })
}

useEffect(() => {
  // Add reCaptcha
  const script = document.createElement("script")
  script.src = "https://www.google.com/recaptcha/api.js?render=_reCAPTCHA_site_key"
  script.addEventListener("load", handleLoaded)
  document.body.appendChild(script)
}, [])

return (
  <div
    className="g-recaptcha"
    data-sitekey="_reCAPTCHA_site_key_"
    data-size="invisible"
  ></div>
)

Answered by Alex Dunlop on December 3, 2020

Try this one! https://github.com/t49tran/react-google-recaptcha-v3 npm install react-google-recaptcha-v3

Answered by Carlos Vieira on December 3, 2020

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP