Seamless Bot Protection: Integrating Cloudflare Turnstile with Nuxt 3

Cloudflare Turnstile offers a modern, visual CAPTCHA-free approach to shield your web applications and forms from malicious bots. For developers working with Nuxt 3, integrating this powerful solution is streamlined through the dedicated nuxt-turnstile module. This guide walks you through the process, from initial setup to component integration.

1. Install the Nuxt Turnstile Module

Begin by adding the nuxt-turnstile module to your project dependencies. Open your terminal within your Nuxt 3 project directory and execute one of the following commands:

npm install nuxt-turnstile
# or
yarn add nuxt-turnstile

2. Configure Your Cloudflare Turnstile Widget

To obtain the necessary keys for your application, you’ll need to set up a Turnstile widget on Cloudflare:

  1. Access Cloudflare: Log in to your Cloudflare account. If you don’t have one, you can create a free account.
  2. Navigate to Turnstile: Head to the “Turnstile” section in your Cloudflare dashboard.
  3. Add a New Widget: Click on “Add Widget.” You’ll be prompted to configure your new widget.
  4. Define Site Details:
    • Provide a descriptive name for your site or project.
    • Crucially, add your application’s domain(s) (hostnames). Even for testing, you can use a free temporary domain if you don’t have a production one yet. Click “Add hostnames,” enter your domain, and confirm.
  5. Retrieve Your Keys: Once configured, Cloudflare will generate two essential keys:
    • Site Key (Public): Used on your frontend.
    • Secret Key (Private): Used for backend validation.

Keep these keys secure, especially the secret key.

3. Configure Nuxt 3 Project Environment

Next, integrate your Cloudflare Turnstile keys into your Nuxt 3 project’s configuration:

  1. Create/Update .env file: In the root of your project, ensure you have a .env file. Add your Site Key and Secret Key to this file. Remember, the values below are placeholders:
    TURNSTILE_SITE_KEY = 'your_cloudflare_site_key_here'
    TURNSTILE_SECRET_KEY = 'your_cloudflare_secret_key_here'
    
  2. Update nuxt.config.ts: Modify your nuxt.config.ts file to include the nuxt-turnstile module and expose the keys via runtimeConfig:
    export default defineNuxtConfig({
      // Add the turnstile module
      modules: ["@nuxtjs/turnstile"],
    
      // Configure runtime environment variables
      runtimeConfig: {
        turnstile: {
          secretKey: process.env.TURNSTILE_SECRET_KEY, // Keep secret key server-side
        },
        public: {
          turnstile: {
            siteKey: process.env.TURNSTILE_SITE_KEY, // Expose site key publicly
          }
        }
      }
    })
    

4. Integrate Turnstile into Your Nuxt Component

Now you’re ready to place the Turnstile widget within your application’s components, typically on forms (e.g., login, registration, contact forms).

Here’s an example of integrating NuxtTurnstile into a basic login form:

<script setup lang="ts">
import { ref } from 'vue'

const form = ref({
  email: '',
  password: ''
})

const turnstileToken = ref('') // Reactive variable to store the Turnstile token

const handleSubmit = () => {
  if (!turnstileToken.value) {
    alert('Please complete the Turnstile challenge before submitting!')
    return
  }

  // Your form submission logic goes here,
  // including sending turnstileToken.value to your backend for verification.
  console.log('Form submitted:', {
    ...form.value,
    turnstileToken: turnstileToken.value
  })
}
</script>

<template>
  <form
    class="max-w-sm mx-auto space-y-6 p-6 border rounded-xl shadow-lg bg-white"
    @submit.prevent="handleSubmit"
  >
    <h2 class="text-2xl font-bold text-center">Login</h2>

    <div>
      <label class="block text-sm font-medium mb-1">Email</label>
      <input
        v-model="form.email"
        type="email"
        placeholder="Enter your email"
        class="w-full px-3 py-2 border rounded-md focus:ring focus:ring-blue-400"
        required
      />
    </div>

    <div>
      <label class="block text-sm font-medium mb-1">Password</label>
      <input
        v-model="form.password"
        type="password"
        placeholder="Enter your password"
        class="w-full px-3 py-2 border rounded-md focus:ring focus:ring-blue-400"
        required
      />
    </div>

    <!-- The NuxtTurnstile component -->
    <NuxtTurnstile
      v-model="turnstileToken"
      :options="{
        theme: 'auto', // or 'light', 'dark'
        size: 'normal', // or 'compact'
        action: 'login', // A custom action name for analytics
        language: 'pt-BR' // Set the widget language
      }"
    />

    <button
      type="submit"
      class="w-full py-2 px-4 bg-blue-600 text-white font-semibold rounded-lg shadow hover:bg-blue-700 transition"
    >
      Login
    </button>
  </form>
</template>

When rendered, the NuxtTurnstile component will display a discreet challenge (often invisible to legitimate users) that verifies the user is human. The generated token is then bound to turnstileToken.value.

Backend Token Validation

Crucially, after a user submits the form and you receive the turnstileToken on your backend, you must validate this token with Cloudflare using your Secret Key. This step ensures the token is legitimate and prevents bots from bypassing the frontend check.

By following these steps, you can effectively integrate Cloudflare Turnstile into your Nuxt 3 application, enhancing security without sacrificing user experience.

Leave a Reply

Your email address will not be published. Required fields are marked *

Fill out this field
Fill out this field
Please enter a valid email address.
You need to agree with the terms to proceed