"If a worker wants to do his job well, he must first sharpen his tools." - Confucius, "The Analects of Confucius. Lu Linggong"
Front page > Programming > Migrating from Google&#s reCAPTCHA to Cloudflare Turnstile?

Migrating from Google&#s reCAPTCHA to Cloudflare Turnstile?

Published on 2024-07-31
Browse:498

Migrating from Google

Google reCAPTCHA new pricing will be rolled out on August 1st, meaning that you have a few days left to migrate to a cheaper alternative or ensure your bank account is well-funded.

Starting at $1 for 1,000 verifications, it is going to cost a lot. At Mailmeteor, we use reCAPTCHA extensively to protect our services from bots. With Google's pricing change, we calculated that we're about to pay thousands of dollar per month to keep using their reCAPTCHA service.

What's a CAPTCHA?

CAPTCHAs are an essential part of the web. It aims to separate good citizens from bad actors. Essentially, it's a service that will operate on the frontend and generate a token that is transmitted to the backend. The backend then verifies that the token is legit, and, if so, performs the action.

Google did a great job at promoting their own service, but thankfully, there are some alternatives:

  1. hCaptcha. We considered it at first, but their pricing is quite similar to new Google's pricing.
  2. Cloudflare Turnstile. We are huge fans of Cloudflare, and definitely looked into it. As for now, it's a free service.

Let's dig in.

Moving away from Google reCAPTCHA...

One of our free tools is an AI Email Writer. It's basically an HTML page that send request to our backend, which then makes to a third-party AI solution.

To protect it from abuse, Google reCAPTCHA was enabled from day one. Here's how the verification was done so far (backend-side):

// index.js
app.post('/api/email-ai-writer', recaptcha.middleware.verify, aiEmailWriter)

// ai_email_writer.js
async function aiEmailWriter(request, response) {
  try {
    // Recaptcha
    if (!request.recaptcha || request.recaptcha.error || !request.recaptcha.data) {
      console.warn('Recaptcha: verification failed.')
      return response.status(403).send({ error: true, message: 'Recaptcha: verification failed' })
    } else if (request.recaptcha.data.action !== 'aiemailwriter') {
      console.warn('Recaptcha: bad action name')
      return response.status(403).send({ error: true, message: 'Recaptcha: bad action name' })
    } else if (request.recaptcha.data.score 



That's quite simple and it's an essential part of why Google reCAPTCHA was so popular. The footprint is very limited and it's really easy to implement. For the most curious ones, we leveraged the express-recaptcha package to make it really easy to implement.

... to Cloudflare Turnstile

When migrating to Turnstile, we couldn't found an NPM package, so we had to write a middleware to process the token. Here's how it looks like:

// middlewares/turnstile.js
const turnstile = async (request, response, next) => {
  try {
    // Turnstile injects a token in "cf-turnstile-response".
    const token = request.query['cf-turnstile-response']
    const ip = request.header('CF-Connecting-IP')

    if (!token) {
      throw new Error('Missing CloudFlare Turnstile Token')
    }

    // Validate the token by calling the
    // "/siteverify" API endpoint.
    const formData = new FormData()
    formData.append('secret', process.env.CLOUDFLARE_TURNSTILE_SECRET_KEY)
    formData.append('response', token)
    if (ip) formData.append('remoteip', ip)

    const url = 'https://challenges.cloudflare.com/turnstile/v0/siteverify'
    const result = await fetch(url, {
      body: formData,
      method: 'POST',
    })

    // Process the verification outcome
    const outcome = await result.json()

    if (!outcome.success) {
      throw new Error('CloudFlare Turnstile declined the token')
    }

    request.turnstile = outcome

    // If authentified, go to next middleware
    next()
  } catch (err) {
    console.error(err)
    return response.status(403).send('Forbidden')
  }
}

export { turnstile }

Once the middleware is in place, we can apply it to any requests:

// index.js
app.post('/api/ai-email-writer', aiRateLimiter, turnstile, aiEmailWriter)

And inside the function that treats the request, it's quite similar to what we had previously:

// ai_email_writer.js
async function aiEmailWriter(request, response) {
  try {
    // CloudFlare Turnstile protection
    if (!request.turnstile || request.turnstile.error) {
      console.warn('Recaptcha: verification failed.')
      return response.status(403).json({ error: true, message: 'Recaptcha: verification failed' })
    } else if (request.turnstile.action !== 'aiemailwriter') {
      console.warn('Recaptcha: bad action name')
      return response.status(403).json({ error: true, message: 'Recaptcha: bad action name' })
    }

    ...

Conclusion

Migrating from reCAPTCHA to Turnstile is straightforward and shouldn't take more than a few hours. It works quite similar and will definitely save you a lot of money at the same time.

I didn't cover the frontend in this article, because we use an invisible widget that our users don't see. But Turnstile's documentation covers extensively how to use their interactive widgets.

Call it a day!

Release Statement This article is reproduced at: https://dev.to/frenchcooc/migrating-from-googles-recaptcha-to-cloudflare-turnstile-17lf?1 If there is any infringement, please contact [email protected] to delete it
Latest tutorial More>

Disclaimer: All resources provided are partly from the Internet. If there is any infringement of your copyright or other rights and interests, please explain the detailed reasons and provide proof of copyright or rights and interests and then send it to the email: [email protected] We will handle it for you as soon as possible.

Copyright© 2022 湘ICP备2022001581号-3