Skip to content
Esc
navigateopen⌘Jpreview
Dashboard
On this page

CAPTCHA

Use the plugin to add CAPTCHA to your authentication flow.

Overview

This following tutorial shows you how to add CAPTCHA validation to your authentication flows. The guide makes use of the plugins functionality. A new abstraction layer aimed to simplify how you can add new features in your SuperTokens integration.

Before you start

The plugin supports only the React and NodeJS SDKs. Support for other platforms is under active development.

You can use the plugin with the following CAPTCHA providers:

Make sure to have the appropriate provider keys before starting the tutorial.

The implementation is in early stages and APIs might change. For more information on how plugins work refer to the references page.

Steps

1. Initialize the frontend plugin

1.1 Install the plugin

npm install @supertokens-plugins/captcha-react

1.2 Update your frontend SDK configuration

import SuperTokens from "supertokens-auth-react";
import CaptchaPlugin from "@supertokens-plugins/captcha-react";

SuperTokens.init({
  appInfo: {
    appName: "...",
    apiDomain: "...",
    websiteDomain: "...",
  },
  recipeList: [
    // your recipes
  ],
  experimental: {
    plugins: [
      CaptchaPlugin.init({
        type: "reCAPTCHAv3", // or "reCAPTCHAv2" or "turnstile"
        captcha: {
          sitekey: "your-site-key",
          // Additional configuration based on the captcha provider
        },
      }),
    ],
  },
});

2. Initialize the backend plugin

2.1 Install the plugin

npm install @supertokens-plugins/captcha-nodejs

2.2 Update your backend SDK configuration

import SuperTokens from "supertokens-node";
import CaptchaPlugin from "@supertokens-plugins/captcha-nodejs";

SuperTokens.init({
  supertokens: {
    connectionURI: "...",
  },
  appInfo: {
    appName: "...",
    apiDomain: "...",
  },
  recipeList: [
    // your recipes
  ],
  experimental: {
    plugins: [
      CaptchaPlugin.init({
        type: "reCAPTCHAv3", // or "reCAPTCHAv2" or "turnstile"
        captcha: {
          secretKey: "your-secret-key",
        },
      }),
    ],
  },
});

3. Customize the plugin

By default, the plugin performs CAPTCHA validation on the following authentication flows:

Recipe Authentication Flow Forms Pre-API Hook Action API Function
EmailPassword User sign in EmailPasswordSignInForm EMAIL_PASSWORD_SIGN_IN signInPOST
EmailPassword User registration EmailPasswordSignUpForm EMAIL_PASSWORD_SIGN_UP signUpPOST
EmailPassword Password reset request EmailPasswordResetPasswordEmail SEND_RESET_PASSWORD_EMAIL generatePasswordResetTokenPOST
EmailPassword Password reset submission EmailPasswordSubmitNewPassword SUBMIT_NEW_PASSWORD passwordResetPOST
Passwordless Generate verification code PasswordlessEmailForm and PasswordlessPhoneForm and PasswordlessEmailOrPhoneForm PASSWORDLESS_CREATE_CODE createCodePOST
Passwordless Verify code and sign in PasswordlessUserInputForm PASSWORDLESS_CONSUME_CODE consumeCodePOST

To limit which actions require additional validation, pass additional configuration parameters to the frontend and backend setup steps.

Frontend conditional validation

On the frontend create a custom component that conditionally loads the CAPTCHA provider based on the name of the form.

import { forwardRef, useEffect } from "react";
import type { ComponentPropsWithoutRef } from "react";
import SuperTokens from "supertokens-auth-react";
import CaptchaPlugin, { useCaptcha, useCaptchaInputContainer } from "@supertokens-plugins/captcha-react";

type CaptchaInputContainerProps = ComponentPropsWithoutRef<ReturnType<typeof useCaptchaInputContainer>>;

const CaptchaInputContainer = forwardRef<HTMLDivElement, CaptchaInputContainerProps>((props, ref) => {
  const { form, ...rest } = props;
  const { load, render, containerId } = useCaptcha();

  useEffect(() => {
    // CAPTCHA applies/renders only for the EmailPasswordSignUpForm
    // and the EmailPasswordResetPasswordEmail
    if (form === "EmailPasswordSignUpForm" || form === "EmailPasswordResetPasswordEmail") {
      void load().then(() => render());
    }
  }, [form, load, render]);

  return (
    <div
      ref={ref}
      id={typeof containerId === "string" ? containerId : undefined}
      className="CAPTCHA-container"
      {...rest}
    />
  );
});

SuperTokens.init({
  appInfo: {
    appName: "...",
    apiDomain: "...",
    websiteDomain: "...",
  },
  recipeList: [
    // your recipes
  ],
  experimental: {
    plugins: [
      CaptchaPlugin.init({
        type: "reCAPTCHAv3", // or "reCAPTCHAv2" or "turnstile"
        captcha: {
          sitekey: "your-site-key",
        },
        InputContainer: CaptchaInputContainer,
      }),
    ],
  },
});

Backend conditional validation

On the backend pass a custom validation function that tells the plugin which actions should require extra validation.

import SuperTokens from "supertokens-node";
import CaptchaPlugin, { SuperTokensPluginCaptchaConfig } from "@supertokens-plugins/captcha-nodejs";

const shouldValidate: NonNullable<SuperTokensPluginCaptchaConfig["shouldValidate"]> = (api, input) => {
  // Only require CAPTCHA for sign up
  if (api === "signUpPOST") {
    return true;
  }

  // Check request headers for suspicious activity
  if (api === "signInPOST") {
    const userAgent = input.options.req.getHeaderValue("user-agent");
    return !userAgent || userAgent.includes("bot");
  }

  return false;
};

SuperTokens.init({
  supertokens: {
    connectionURI: "...",
  },
  appInfo: {
    appName: "...",
    apiDomain: "...",
  },
  recipeList: [
    // your recipes
  ],
  experimental: {
    plugins: [
      CaptchaPlugin.init({
        type: "reCAPTCHAv3", // or "reCAPTCHAv2" or "turnstile"
        captcha: {
          secretKey: "your-secret-key",
        },
        shouldValidate,
      }),
    ],
  },
});

Next steps

Besides CAPTCHA validation you can also look into the Attack Protection Suite feature which provides prevention against suspicious authentication attempts.

API reference

API schema and response details