nuxt-modules / turnstile

🔥 Cloudflare Turnstile integration for Nuxt
https://cloudflare.com/products/turnstile
MIT License
216 stars 17 forks source link

The `verifyTurnstileToken` helper doesn't work on Cloudflare Pages serverless functions #256

Closed Yizack closed 1 year ago

Yizack commented 1 year ago

🐛 The bug

Hello, I've been using the @nuxtjs/turnstile module on Cloudflare Pages for some time now and I just wanted to share a problem I encountered using the module and how I solved it.

So, the bug is while using the verifyTurnstileToken helper, it always returns with a missing-input-secret error even if I have the NUXT_TURNSTILE_SECRET_KEY set. It works perfectly in local and development enviroment.

If I'm not mistaken, I really think this error comes from the fact that on Cloudflare Workers and Pages, the event argument must be passed with the useRuntimeConfig function so the serverless function can access to the enviroment variables.

Since this is a production only "bug", unfortunately I can't give a stackblitz link to reproduce using the playground, alternatively to reproduce the error I created a repo with the steps to reproduce here: https://github.com/Yizack/nuxt-turnstile-cf-rep

What I did to solve this problem was this. At verify.ts I thought that by adding an optional event parameter and use the useRuntimeConfig inside the helper function could make it work and it worked.

import type { H3Event } from 'h3' // ✔️
import type { TurnstileValidationResponse } from '../../types'

// @ts-expect-error nitro aliases aren't registered
import { useRuntimeConfig } from '#internal/nitro'

// const secretKey = useRuntimeConfig().turnstile.secretKey  // ❌
const endpoint = 'https://challenges.cloudflare.com/turnstile/v0/siteverify'

export const verifyTurnstileToken = async (token: string, event?: H3Event): Promise<TurnstileValidationResponse> => { // ✔️
  const secretKey = useRuntimeConfig(event).turnstile.secretKey // ✔️
  return await $fetch(endpoint, {
    method: 'POST',
    body: `secret=${encodeURIComponent(secretKey)}&response=${encodeURIComponent(token)}`,
    headers: {
      'content-type': 'application/x-www-form-urlencoded',
    },
  })
}

🛠️ To reproduce

https://github.com/Yizack/nuxt-turnstile-cf-rep

🌈 Expected behaviour

Turnstile verification should pass on Cloudflare Pages.

ℹ️ Additional context

I will open a PR in case this bug is not intended and hope you think this is a propper approach

danielroe commented 1 year ago

That would be great - thank you!