Integrating Nuxt 3 with Recaptcha v3 for Token Handling 🤖🔐

fitrakun

Fitra Rahmamuliani

Posted on January 9, 2024

Integrating Nuxt 3 with Recaptcha v3 for Token Handling 🤖🔐

Introduction

Embarking on the journey of web development with Nuxt 3 and Recaptcha v3 can be both thrilling and challenging. Today, I tried unveil a solution that simplifies the integration process, especially when dealing with the mysterious g-recaptcha-token that being needed by the API. We need to provide it as a field when submitting a post request to the API for backend purpose: to make sure that the recaptcha token received is matching with the setup of the recaptcha token saved from the backend. If you've ever struggled with the token being undefined in production even though we already trying to use the tutorial from the vue-recaptcha-v3, me too!

In this article, I will unravel the intricacies and provide a step-by-step guide to empower developers with javascript only (no typescript) in their quest for a flawless integration. Hope it will helps you.

Part 1: Plugins - The Gateway to Recaptcha Power

Before started, please make sure that you already install the vue-recaptcha-v3.

Plugins serve as the gateway to injecting external functionalities into your Nuxt 3 project. To kickstart the integration process, create a dedicated plugin for Recaptcha v3 on plugins/recaptcha.js.

// plugins/recaptcha.js
import { VueReCaptcha } from 'vue-recaptcha-v3'
// The plugin enables the usage of Google reCAPTCHA in a Nuxt.js application
// by registering the VueReCaptcha plugin with the necessary configuration options.
export default defineNuxtPlugin(nuxtApp => {
  const config = useRuntimeConfig()

  const options = {
    siteKey: config.public.RECAPTCHA_SITE_KEY,
    loaderOptions: {
      autoHideBadge: true,
      useRecaptchaNet: true,
      renderParameters: {
        hl: 'id'
      }
    }
  }
  nuxtApp.vueApp.use(VueReCaptcha, options)
})

Enter fullscreen mode Exit fullscreen mode

Part 2: Composable - The Art of Reusable Logic

Create a composable to encapsulate the logic for handling Recaptcha interactions. This composable will be the engine that drives the token generation process.

Please make sure that you save it on the composables folder.

// composables/useGoogleRecaptcha.js

import { useReCaptcha } from 'vue-recaptcha-v3'
/**
 * The exported executeRecaptcha function allows
 * you to execute reCAPTCHA actions
 * and retrieve the reCAPTCHA token along with the header options
 * to be used in subsequent requests.
 */
export default () => {
  const recaptchaInstance = useReCaptcha()
  const executeRecaptcha = async action => {
    /**
     * Wait for the recaptchaInstance to be loaded
     * by calling the recaptchaLoaded method.
     * This ensures that the reCAPTCHA library is fully loaded
     * and ready to execute reCAPTCHA actions.
     */
    await recaptchaInstance?.recaptchaLoaded()
    const token = await recaptchaInstance?.executeRecaptcha(action)
    const headerOptions = {
      headers: {
        'google-recaptcha-token': token
      }
    }
    return { token, headerOptions }
  }
  return { executeRecaptcha }
}

Enter fullscreen mode Exit fullscreen mode

Part 3: Calling the Function - Bridging the Frontend and Backend

Now that we have our Recaptcha composable ready, let's integrate it into our component and call the function whenever needed.

In this example, we use NuxtApiParty for handling the api that they will generate the useApiData based on our config. You can learn more about NuxtApiParty here: https://nuxt-api-party.byjohann.dev/

<template>
  <!-- insert code for your component's template -->
</template>

<script setup>
// other functions

const { executeRecaptcha } = useGoogleRecaptcha()

// the function where you submit the form 
const submitForm = async values => {
  isSubmitting.value = true
const { token } = await executeRecaptcha('submit')
// console.log(token) -> to make sure there is the token

// combine the form value with g-recaptcha-response that we need to send via api
const bodyData = {
    ...formData.value,
    'g-recaptcha-response': token
}

const { pending, error } = await useApiData(
    `/api/form_submissions`,
    {
      method: 'post',
      cache: false,
      body: bodyData
    }
  )

  if (error.value) {
    isSubmitting.value = pending.value
    showFail.value = true
  } else {
    isSubmitting.value = pending.value
    clearForm()
    showSuccess.value = true
  }
}

// other functions 
</script>
Enter fullscreen mode Exit fullscreen mode

Additional step (if your plugins are not being called)

All plugins inside are auto-registered, you don't need to add them to your nuxt.config separately.
source: Thanks to
Thiru for sending this source https://nuxt.com/docs/guide/directory-structure/plugins

If you have already registered but are not being called (special case), you can try this additional step:

Nuxt Config - Configuring the Nexus of Nuxt 3 and Recaptcha

Now, let's configure Nuxt to incorporate the Recaptcha plugin seamlessly. Open your nuxt.config.ts file and include the plugin in the plugins array.

// nuxt.config.ts

// https://nuxt.com/docs/api/configuration/nuxt-config
export default defineNuxtConfig({
  // {insert CODE for other Nuxt config options}

  // Include the Recaptcha plugin
  plugins: [{src: '~/plugins/recaptcha.js'}],

  // {insert CODE for other Nuxt config options}
};
Enter fullscreen mode Exit fullscreen mode

Conclusion:

Congratulations! You've embarked on a journey to seamlessly integrate Nuxt 3 with Recaptcha v3, overcoming the challenges associated with g-recaptcha-token (getting the token sent to the API). This solution ensures a smooth transition from development to production, empowering developers to create secure and reliable web applications. Happy coding!

Reference:

💖 💪 🙅 🚩
fitrakun
Fitra Rahmamuliani

Posted on January 9, 2024

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related