Using reCAPTCHA on a Astro form
By Flavio Copes
Learn how to add Google reCAPTCHA to an Astro form to stop spam, wiring the widget with your site key and verifying the response on the server with siteverify.
~~~
Here’s how I used Recaptcha on a Astro form to prevent spam and form submission abuse.
Set Recaptcha first, and grab the RECAPTCHA_SITE_KEY and RECAPTCHA_SECRET_KEY variables, put them in .env or anywhere you manage env vars.
Then in the Astro component:
<script
is:inline
src='https://www.google.com/recaptcha/api.js'></script>
<script is:inline>
function recaptcha() {
document.querySelector('form').submit()
}
</script>
<form method='post'>
...
<input
type='submit'
class='block w-full px-3 py-2 mt-8 text-sm font-semibold text-center text-white cursor-pointer leading-6 rounded-md g-recaptcha focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-blue-600 ring-1 ring-inset ring-blue-200 hover:ring-blue-300 hover:bg-blue-600'
data-sitekey={import.meta.env
.RECAPTCHA_SITE_KEY ||
process.env.RECAPTCHA_SITE_KEY}
data-callback='recaptcha'
data-action='submit'
value='Login'
/>
</form>
Server-side form POST request handler:
export async function processCaptcha(g_recaptcha_response: string) {
const url =
'https://www.google.com/recaptcha/api/siteverify'
const requestBody = new URLSearchParams({
secret:
import.meta.env.RECAPTCHA_SECRET_KEY ||
process.env.RECAPTCHA_SECRET_KEY,
response: g_recaptcha_response
})
const response = await fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
body: requestBody.toString()
})
const data = await response.json()
console.log(data)
/*
{
success: true,
challenge_ts: '2024-01-20T18:18:12Z',
hostname: 'localhost',
score: 0.9,
action: 'submit'
}
*/
return data.success
}
if (Astro.request.method === 'POST') {
const formData = await Astro.request.formData()
const email = formData.get('email')?.toString() || ''
const password =
formData.get('password')?.toString() || ''
const g_recaptcha_response =
formData.get('g-recaptcha-response')?.toString() || ''
const is_valid_captcha = await processCaptcha(g_recaptcha_response)
if (!is_valid_captcha) {
error = 'Invalid captcha'
} else {
//valid
}
}~~~
Related posts about astro: