Blog
hCaptcha, a bot detection tool, usage in Supabase and Chatwoot

hCaptcha, a bot detection tool, usage in Supabase and Chatwoot

In this article, you will learn what is hCaptcha and its usage in Open Source projects such as Supabase and Chatwoot.

What is hCaptcha?

hCaptcha helps you detect bots. when you have a public facing form such as signin/signup, you could have bots spamming your systems. This is where hCaptcha comes into picture, it provides a captcha for a user to solve the puzzle so bots are not allowed to sign up.

Link to official website — https://www.hcaptcha.com/

hCaptcha docs

hCaptcha docs is built using Docusaurus and their developer guide provides a vanilla example, but there’s framework specific examples provided as well.

hCaptcha usage in Supabase

In Supabase’s SignInForm.tsx, at line 124, you will find the below code:

<div className="self-center">
 <HCaptcha
   ref={captchaRef}
   sitekey={process.env.NEXT_PUBLIC_HCAPTCHA_SITE_KEY!}
   size="invisible"
   onVerify={(token) => {
     setCaptchaToken(token)
   }}
   onExpire={() => {
     setCaptchaToken(null)
   }}
 />
</div>

hCaptcha is imported from react-hcaptcha.

import HCaptcha from '@hcaptcha/react-hcaptcha'

In the onSignin function, hCaptcha is processed as shown below:

const [captchaToken, setCaptchaToken] = useState<string | null>(null)
const captchaRef = useRef<HCaptcha>(null)

let token = captchaToken
 
if (!token) {
 const captchaResponse = await captchaRef.current?.execute({ async: true })
 token = captchaResponse?.response ?? null
}
 
const { error } = await auth.signInWithPassword({
 email,
 password,
 options: { captchaToken: token ?? undefined },
})

hCaptcha usage in Chatwoot

In the Chatwoot Signup form, you will find the below code at line 186:

<div v-if="globalConfig.hCaptchaSiteKey" class="mb-3">
  <VueHcaptcha
    ref="hCaptcha"
    :class="{ error: !hasAValidCaptcha && didCaptchaReset }"
    :sitekey="globalConfig.hCaptchaSiteKey"
    @verify="onRecaptchaVerified"
  />
  <span
    v-if="!hasAValidCaptcha && didCaptchaReset"
    class="text-xs text-red-400"
  >
    {{ $t('SET_NEW_PASSWORD.CAPTCHA.ERROR') }}
  </span>
</div>

This is in Vue.js, based on @verify=”onRecaptchaVerified”, we should be looking for a function named onRecaptchaVerified. In the methods, hcaptcha related functions are found as shown below:

methods: {
    async submit() {
      this.v$.$touch();
      if (this.v$.$invalid) {
        this.resetCaptcha();
        return;
      }
      this.isSignupInProgress = true;
      try {
        await register(this.credentials);
        window.location = DEFAULT_REDIRECT_URL;
      } catch (error) {
        let errorMessage =
          error?.message || this.$t('REGISTER.API.ERROR_MESSAGE');
        this.resetCaptcha();
        useAlert(errorMessage);
      } finally {
        this.isSignupInProgress = false;
      }
    },
    onRecaptchaVerified(token) {
      this.credentials.hCaptchaClientResponse = token;
      this.didCaptchaReset = false;
    },
    resetCaptcha() {
      if (!this.globalConfig.hCaptchaSiteKey) {
        return;
      }
      this.$refs.hCaptcha.reset();
      this.credentials.hCaptchaClientResponse = '';
      this.didCaptchaReset = true;
    },
  },
};

About me:

Hey, my name is Ramu Narasinga. I study large open-source projects and create content about their codebase architecture and best practices, sharing it through articles, videos.

I am open to work on interesting projects. Send me an email at ramu.narasinga@gmail.com

My Github — https://github.com/ramu-narasinga

My website — https://ramunarasinga.com

My Youtube channel — https://www.youtube.com/@thinkthroo

Learning platform — https://thinkthroo.com

Codebase Architecture — https://app.thinkthroo.com/architecture

Best practices — https://app.thinkthroo.com/best-practices

Production-grade projects — https://app.thinkthroo.com/production-grade-projects

References:

  1. https://github.com/supabase/supabase/blob/master/apps/studio/components/interfaces/SignIn/SignInForm.tsx#L22

  2. https://github.com/chatwoot/chatwoot/blob/4fd9bddb9de08666f7b65ba4b3509f02080ea62d/app/javascript/v3/views/auth/signup/components/Signup/Form.vue#L8

  3. https://www.hcaptcha.com/

  4. https://docs.hcaptcha.com/

  5. https://docusaurus.io/

  6. https://github.com/supabase/supabase/blob/master/apps/studio/components/interfaces/SignIn/SignInForm.tsx#L124

  7. https://github.com/supabase/supabase/blob/master/apps/studio/components/interfaces/SignIn/SignInForm.tsx#L30

  8. https://github.com/chatwoot/chatwoot/blob/4fd9bddb9de08666f7b65ba4b3509f02080ea62d/app/javascript/v3/views/auth/signup/components/Signup/Form.vue#L186