Integrating Nuxt 3 with Recaptcha v3 for Token Handling 🤖🔐
Tags: nuxt3, recaptcha, javascript, webdev
Published: 2024-01-09 06:53:07

## 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](https://www.npmjs.com/package/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](https://www.npmjs.com/package/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`. 

```javascript
// 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)
})

```

## 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.

```javascript
// 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 }
}

```

## 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](https://nuxt.com/modules/api-party) for handling the api that they will generate the `useApiData` based on our config. You can learn more about [NuxtApiParty](https://nuxt.com/modules/api-party) here: [https://nuxt-api-party.byjohann.dev/](https://nuxt-api-party.byjohann.dev/)

```html
<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>
```

### 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](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.

```javascript
// 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}
};
```


## 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:
 
- [https://mehmetozanguven.com/spring-boot/integrate-recaptcha-v3-into-spring-boot-and-vue/](https://mehmetozanguven.com/spring-boot/integrate-recaptcha-v3-into-spring-boot-and-vue/)