How to integrate hCaptcha into a vuejs application?

How to integrate hCaptcha into a vuejs application?

Shailendra Singh's photo
·

5 min read

A few days back I was trying to integrate hCaptcha into a vuejs application which is being hosted on Cloudflare pages. It is a full stack application where backend code is written using Cloudflare pages functions. Although this post has been written in the context of vuejs and Cloudflare, you can use the instructions described here to implement it for any application where frontend has been written using a client-side framework and backend has been written in any server-side programming language.

Although Cloudflare provides a hCaptcha plugin for pages applications, it didn't work for me for some unknown reasons and I couldn't figure out the reason behind the same either. This was good in a way as I always prefer a generic solution which is platform/framework agnostic and which makes it easy to implement a solution across a number of platform/frameworks with the same approach.

Why do you need hCaptcha?

Many times you will have one or more API endpoints which you want to expose to the end users but which should not be protected. One such example is an endpoint which is used to sign up users to an application where such application should be accessed by logged-in users only. You can't have authentication/authorization enabled for such endpoints as it will prevent a user from creating an account for himself to access your protected application. However, having such a public endpoint can result in bad actors (e.g. bots/automation) abusing such endpoints by creating multiple accounts in a short period leading to multiple issues -

  • Such an endpoint must be highly available otherwise new users will not be able to access your protected application if they are unable to create an account for themselves. If a bot or an automation is accessing this endpoint frequently to create multiple accounts in a short period then it may hurt the high availability of such an endpoint.

  • Your application is meant to be accessed by humans only but a bad actor is trying to put much more stress on your system/infra by sending much more traffic to your system than what you are expecting from a single user by abusing such unprotected endpoints.

  • This will make it difficult to plan for the capacity required to handle a certain number of users.

  • This may result in giving you a false impression of the high number of registered users when the actual user count may be very low.

How does hCaptcha work under the hood?

To eliminate the problems described above, you will need to come up with a solution which makes it impossible/difficult for bots/automation to execute an unprotected endpoint multiple times in a very short period. To achieve this with hCaptcha you will need to integrate hCaptcha both on frontend as well as backend.

Once you integrate hCaptcha with a frontend, it will show a challenge to the end user. Once a user solves the challenge successfully, it will then generate a token. This token should be posted to the backend along with any other data required by the backend. This token can be posted either as a header (preferred) or in the request body.

Upon receiving this token, your backend API should post this token to an API (hcaptcha.com/siteverify) provided by hCaptcha which will validate this token and return a success or failure response depending on whether the token is valid or not. If the token is valid then you will continue executing the target endpoint. Otherwise, terminate the execution at that point and return a failure response status code (e.g. 403) to the client.

Integrating hCaptcha with your application

Frontend (vuejs)

hCaptcha provides an npm module for both vuejs 2 and 3 which you can use to integrate hCaptcha into a vuejs application. It can be installed using the following commands -

npm

vue2: npm install @hcaptcha/vue-hcaptcha --save
vue3: npm install @hcaptcha/vue3-hcaptcha --save

yarn

vue2: yarn add @hcaptcha/vue-hcaptcha
vue3: yarn add @hcaptcha/vue3-hcaptcha

Add vue-hcaptcha tag at a place in your vuejs component where you would like to render the hCaptcha block -

<template>
<!-- username -->
<!-- password -->
<vue-hcaptcha 
   @verify="updateCaptchaToken"
>
</vue-hcaptcha>
<!-- button to handle form submission -->
</template>

<script setup>
import VueHcaptcha from '@hcaptcha/vue3-hcaptcha'

const captchaToken = ref('')

function updateCaptchaToken(token, ekey) {
  captchaToken.value = token
  console.log('Captcha token : ' + captchaToken.value)
}
</script>

Upon solving the challenge successfully, vue-hcaptcha triggers an event named verify and passes two string parameters to the handler of this event. The first parameter will be a token which you will be posting to the backend and the second parameter is something which is required for enterprise customers and which we will not cover in this post.

Now you will need to write a function which will be invoked on clicking of some button which will then pass this token in a header named captcha-token. You can choose any name for this header.

Backend

As described in one of the sections above, you will need to retrieve the token from captcha-token header and post it to hcaptcha.com/siteverify endpoint provided by hCaptcha. Here is a sample code to achieve this in a javascript function -

const secret = // a secret required to invoke /siteverify endpoint
const token = // retrieve token from the header

console.log('Captcha token : ' + token)

const validateCaptchaResponse = await fetch(
   'https://hcaptcha.com/siteverify',
   {
      method: 'POST',
      headers: {
         'Content-Type': 'application/x-www-form-urlencoded'
      },
      body: `secret=${secret}&response=${token}`
   }
)

console.log('Validate captcha status code : ' + validateCaptchaResponse.status)
const validateCaptchaResponseBody = await validateCaptchaResponse.json()
console.log('Validate captcha response : ' + JSON.stringify(validateCaptchaResponseBody))

if(validateCaptchaResponseBody.success) {
   // continue execution
} else {
   // return response with a status code (e.g. 403) indicating failure to execute the target endpoint
}

Before you can verify the token posted by frontend with /siteverify endpoint provided by hCaptcha, you will need to generate a secret on hCaptcha website. Simply sign up on the website, click on the profile icon in the upper right corner of the page and then click on settings in the dropdown list. Now click on Get New Secret Key and then update the generated secret against the secret variable (first line) in the sample code posted above. You now have hCaptcha integrated into your application.