DEV Community

Chandra Kodi
Chandra Kodi

Posted on • Updated on

Sitecore - Google ReCaptcha V3

Google developed reCaptcha V3 to improve the accuracy of bot detection and for better user experience. Unlike V2, V3 is transparent as a hidden element and continuously monitors the visitor’s behavior to determine whether it’s a human or a bot.
alt text

Below you can find step by step process to create Google reCaptcha V3 field in Sitecore Forms.

  • Create a new model class - GoogleRecaptchaV3.cs
public class GoogleRecaptchaV3 : StringInputViewModel
    {
        public string ApiKey { get; set; }

        public string ErrorMessage { get; set; }

        protected override void InitItemProperties(Item item)
        {
            base.InitItemProperties(item);

            ApiKey = Sitecore.StringUtil.GetString(item.Fields["Api Key"]);
            ErrorMessage = Sitecore.StringUtil.GetString(item.Fields["Error Message"]);
        }

        protected override void UpdateItemFields(Item item)
        {
            base.UpdateItemFields(item);

            item.Fields["Api Key"].SetValue(ApiKey, true);
            item.Fields["Error Message"].SetValue(ErrorMessage, true);
        }
    }
Enter fullscreen mode Exit fullscreen mode
  • Create custom validation class - CaptchaV3Validator.cs
public class CaptchaV3Validator : ValidationElement<string>
    {
        public override IEnumerable<ModelClientValidationRule> ClientValidationRules
        {
            get
            {
                if (string.IsNullOrEmpty(this.ApiKey))
                {
                    yield break;
                }
            }
        }

        protected virtual string ApiKey { get; set; }
        protected virtual string Title { get; set; }
        protected virtual string FieldName { get; set; }

        public CaptchaV3Validator(ValidationDataModel validationItem) : base(validationItem)
        {

        }

        public override void Initialize(object validationModel)
        {
            base.Initialize(validationModel);
            StringInputViewModel stringInputViewModel = validationModel as StringInputViewModel;
            if (stringInputViewModel != null)
            {
                var fieldItem = Sitecore.Context.Database.GetItem(ID.Parse(stringInputViewModel.ItemId));
                if (fieldItem != null)
                {
                    this.ApiKey = fieldItem["Api Key"];
                }
                this.Title = stringInputViewModel.Title;
                this.FieldName = stringInputViewModel.Name;
            }
        }

        public override ValidationResult Validate(object value)
        {
            if (value == null)
            {
                return new ValidationResult("Captcha is Inavlid.");// ValidationResult.Success;
            }
            var isCaptchaValid = ValidateCaptcha((string)value, this.ApiKey);
            if (!isCaptchaValid)
            {
                return new ValidationResult(this.FormatMessage(new object[] { this.Title }));
            }
            return ValidationResult.Success;
        }
        public static bool ValidateCaptcha(string response, string secret)
        {
            HttpClient httpClient = new HttpClient();

            var res = httpClient.GetAsync($"https://www.google.com/recaptcha/api/siteverify?secret=" + secret + "&response=" + response + "").Result;

            if (res.StatusCode != HttpStatusCode.OK)
                return false;

            string JSONres = res.Content.ReadAsStringAsync().Result;
            dynamic JSONdata = JObject.Parse(JSONres);

            if (JSONdata.success != "true")
                return false;

            return true;
        }
    }
Enter fullscreen mode Exit fullscreen mode
  • Create a View at location Views/FormBuilder/FieldTemplates- GoogleRecaptchaV3.cshtml
@using Sitecore.ExperienceForms.Mvc.Html
@model Glass.Mapper.Training.FormFields.GoogleRecaptchaV3


<input id="@Html.IdFor(m => Model.Value)" name="@Html.NameFor(m => Model.Value)" class="@Model.CssClass" type="hidden" value="" />

<script src="https://www.google.com/recaptcha/api.js?onload=grecaptcha_ready&render=@Model.ApiKey"></script>
<script>
    function grecaptcha_ready() {
        grecaptcha.ready(function () {
            grecaptcha.execute('@Model.ApiKey', { action: 'form' }).then(function (token) {
                document.getElementById("@Html.IdFor(m => Model.Value)").value = token;
            });
        });
    }
    var hiddenField = document.getElementById(@Html.Raw("\"" + Html.IdFor(m => Model.Value) + "\""));
    var parent = hiddenField.parentNode;
    if (parent.classList.contains("sc-formdesign-fieldcontainer")) {
        var textDiv = document.createElement("div");
        textDiv.innerHTML = "(ReCaptcha V3 Hidden Field)";
        parent.appendChild(textDiv);
    }
</script>
Enter fullscreen mode Exit fullscreen mode

Let's move on to the sitecore item changes.

CORE db

  • Create a form property by copying one of existing items ”SingleLineText” and rename the copied item as “GoogleReCaptchaV3”. /sitecore/client/Applications/FormsBuilder/Components/Layouts/PropertyGridForm/PageSettings/Settings/GoogleReCaptchaV3

MASTER db

  • In the Sitecore Content Editor, navigate to /sitecore/templates/System/Forms/Fields.
  • Then add new template with name “CustomRecaptchaV3” and select Base template /sitecore/templates/System/Templates/Template
    alt text

  • This template must inherit as below
    alt text

  • Create new Validation item at /sitecore/system/Settings/Forms/Validations as CaptchaV3 Validation.
    alt text

  • Create new Field type at /sitecore/system/Settings/Forms/Field Types/Security with name Google Recaptcha V3.
    alt text

o View Path: FieldTemplates/GoogleRecaptchaV3
o Model Type: <Namespace>.GoogleRecaptchaV3, <AssemblyName>
o Allowed Validations: CaptchaV3 Validation
o Property Editor: Property Editor Settings/GoogleReCaptchaV3
o Field Template: Fields/Google ReCaptcha V3
o Icon: OfficeWhite/32x32/lock3.png
o BackgroundColor Color: Tomato

Now we are ready to use ReCaptcha V3 in Forms. Go to Sitecore Forms and simply drag and drop Google ReCaptcha V3 field under Security.
alt text

That's it. The ReCaptcha V3 is ready!
alt text

Note: reCAPTCHA v3 returns a score for each request without user friction. The score (between 0 and 1) is based on interactions with your site and you should update script to make decision based on the score according to your application needs. Also, I haven't included token validity but if the default 2 minutes is not enough, then you have to renew/refresh for every two minutes per google's documentation: https://developers.google.com/recaptcha/docs/verify#token_restrictions

Latest comments (6)

Collapse
 
janaranjani profile image
Janaranjani

can we pls post how to implement recaptcha enterprise of type v2 checkbox?

Collapse
 
priyatoconquer profile image
priyatoconquer • Edited

Unable to submit Sitecore Form after adding Google Recaptcha V3 on submit button click getting the below error
Uncaught TypeError: Cannot read properties of undefined (reading 'validator')
at HTMLFormElement.eval (eval at a (jquery.unobtrusive-ajax.min.js:16:157), :3:3)
at Object.success (jquery.unobtrusive-ajax.min.js:16:1361)
at c (jquery-3.4.1.min.js:2:27742)
at Object.fireWith as resolveWith
at l (jquery-3.4.1.min.js:2:78789)
at XMLHttpRequest. (jquery-3.4.1.min.js:2:81117)

Collapse
 
dontspammeyet profile image
DontSpamMeYet

Hello we get this error after following your instructions:
Message: The parameters dictionary contains a null entry for parameter 'templateId' of non-nullable type 'System.Guid' for method 'System.Web.Mvc.ActionResult RenderField(System.Guid, System.Guid)' in 'Sitecore.ExperienceForms.Client.Controllers.FormFieldController'. An optional parameter must be a reference type, a nullable type, or be declared as an optional parameter.Parameter name: parametersSource: System.Web.Mvc

Any idea what it could be? Have found the same questions asked on another forum but no answer for it.

Collapse
 
basselissa profile image
BASEL ISSA

one more important note, that you are mixing between the secret and site key here
the validation should use the secret key not the same site key assigned to the field data

Collapse
 
basselissa profile image
BASEL ISSA

Hello, thanks for the article, does it support multiple recaptcha in the same page,?
and does it work with Sitecore Forms with isAjax enabled?

Collapse
 
bernardbaker profile image
Bernard Baker

Good question