Verify a hCpatcha token with a Cloudflare Worker.
# test the endpoint with curl
curl https://kbsb-hcaptcha-worker.kaboom.workers.dev/form --request POST
# with VSCode REST
POST https://kbsb-hcaptcha-worker.kaboom.workers.dev/form
Visit the React front-end page.
Todos:
- Add more form fields (checkbox, etc)
- Add formvalidation (client- and server-side)
- Finish Light/Dark theme
- Finish the
<Input />
components - Test ReactHookForm / Formik
Uses the react-hcaptcha package. And a standard FormData()
form. The form data is send to a Cloudflare worker. A succesful verification results in a hCaptcha token accepted
server response.
You can find the source code in this repo. The Cloudflare code is located in the cloudflare-worker
directory. The React code in the react-frontend
directory.
"Forms are hard. Forms in React are hard."
Alternatives to a regular <form>
: Formik, React Hook Form
A helpful learning resource: https://mattboldt.com/2020/05/02/formdata-with-react-hooks-and-fetch/. Thanks Matt Boldt.
Process a FormData
hCaptcha token with a Cloudflare Worker. The hCaptcha token is verified with the glenstack
cf-workers-hcaptcha package.
Set up a Worker project. Guide
# install the Cloudflare Wrangler CLI
npm install -g wrangler
# login to Cloudflare
wrangler login
# or get an API key from the Cloudflare account profile page
# initialize project
wrangler init
# start dev server
wrangler dev # needs auhentication
# deploy to production
wrangler publish
wrangler publish --env staging
wrangler publish --env production
If wrangler login
is not possible you can authenticate with a Cloudflare API key. Create a .env file in the worker root folder.
CLOUDFLARE_API_TOKEN=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Adjust the settings in wrangler.toml
.
# for example, set the local host ip/port
[dev]
ip = "100.125.102.16"
port = 8080
# set your CORS policy domain
[env.production.vars]
CORS_ORIGIN = '*' # replace with your frontend domain base-URL including `https://`
// use the CORS variable
console.log(env.CORS_ORIGIN); // make sure to pass env
Before you can validate tokens, you have to upload the hCaptcha secret key to the worker. Get your hCaptcha secret key from the dashboard.
wrangler secret put HCAPTCHA_SECRET_KEY
# paste your key
0x0D00000000000000000000000000000000000000
From Worker docs: "When deploying a Module Worker, any bindings will not be available as global runtime variables. Instead, they are passed to the handler as a parameter – refer to
env
in Parameters."
// pass env as a parameter to the handler
// the variable is now available in your code
console.log(env.HCAPTCHA_SECRET_KEY);
⚠️ Also, set the correct hCaptcha allowed domain(s), for example: https://hcaptcha-cloudflare.kbsb.app/
Cloudflare workers -- in node_compat
mode -- don't support FormData processing packages like Formidable. Therefore, perhaps, a Node/Express/Docker endpoint (deployed on, for example, Fly.io) is just as easy to set up, and more flexible because of the larger Node package ecosystem.
- Implement alternative form validation
This project uses React.js, with yarn,
and the Vite bundler.
# install node_modules
yarn
# run development server
yarn dev
# build the app for production
yarn build
⚠️ Set the correct hCaptcha sitekey and Worker endpoint in the.env
file.
"Request has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource."
Don't forget to add the correct header on the Response object!
// React app
const res = await fetch(endpoint, {
method: 'POST',
body: formData,
mode: 'cors',
// A `no-cors` mode request is restricted, the body can not be read.
});
// Cloudflare worker
return new Response(JSON.stringify(msg: 'unknown endpoint', null, 2), {
headers: {
// add the CORS header
'Access-Control-Allow-Origin': '*',
'content-type': 'application/json;charset=UTF-8',
},
});