Edge Functions

CAPTCHA support with Cloudflare Turnstile


Cloudflare Turnstile is a friendly, free CAPTCHA replacement, and it works seamlessly with Supabase Edge Functions to protect your forms. View on GitHub.

Setup

Code

Create a new function in your project:

1
supabase functions new cloudflare-turnstile

And add the code to the index.ts file:

1
import { corsHeaders } from '../_shared/cors.ts'
2
3
console.log('Hello from Cloudflare Trunstile!')
4
5
function ips(req: Request) {
6
return req.headers.get('x-forwarded-for')?.split(/\s*,\s*/)
7
}
8
9
Deno.serve(async (req) => {
10
// This is needed if you're planning to invoke your function from a browser.
11
if (req.method === 'OPTIONS') {
12
return new Response('ok', { headers: corsHeaders })
13
}
14
15
const { token } = await req.json()
16
const clientIps = ips(req) || ['']
17
const ip = clientIps[0]
18
19
// Validate the token by calling the
20
// "/siteverify" API endpoint.
21
let formData = new FormData()
22
formData.append('secret', Deno.env.get('CLOUDFLARE_SECRET_KEY') ?? '')
23
formData.append('response', token)
24
formData.append('remoteip', ip)
25
26
const url = 'https://challenges.cloudflare.com/turnstile/v0/siteverify'
27
const result = await fetch(url, {
28
body: formData,
29
method: 'POST',
30
})
31
32
const outcome = await result.json()
33
console.log(outcome)
34
if (outcome.success) {
35
return new Response('success', { headers: corsHeaders })
36
}
37
return new Response('failure', { headers: corsHeaders })
38
})

Deploy the server-side validation Edge Functions

1
supabase functions deploy cloudflare-turnstile
2
supabase secrets set CLOUDFLARE_SECRET_KEY=your_secret_key

Invoke the function from your site

1
const { data, error } = await supabase.functions.invoke('cloudflare-turnstile', {
2
body: { token },
3
})