Skip to main content

Sitecore 9 Forms: Google reCaptcha field

Sitecore 9 Forms: Google reCaptcha field 

Re-Captcha is the most important part of any form’s submission. Google reCaptcha run internet bot detector and determined whether a user is a bot or not. 

Sitecore Forms does not provide Google reCaptcha field, which was available in WFFM before, so I have created my custom Google reCaptcha.  

Sitecore 9 Forms Google reCaptcha field

Below you can find step by step process to create Google reCaptcha field.
  • Create patch config for reCaptcha Sitekey and SecretKey
     <?xml version="1.0"?>  
     <configuration xmlns:patch="http://www.sitecore.net/xmlconfig/" xmlns:set="http://www.sitecore.net/xmlconfig/set/">  
      <sitecore>  
       <settings>  
     <setting name="ReCaptchaSiteKey" value="site-key" />  
        <setting name="ReCaptchaSecretKey" value="secret-key" />  </settings>  
     </sitecore>  
     </configuration>  
  • Create new viewmodel class RecaptchaViewModel.cs
     [Serializable()]  
       public class RecaptchaViewModel : MultipleLineTextViewModel  
       {  
         public string SiteKey { get; set; }  
         public string SecretKey { get; set; }  
         public string Message { get; set; }  
         protected override void InitItemProperties(Item item)  
         {  
           base.InitItemProperties(item);  
           string GoogleSiteKey = Configuration.Settings.GetSetting("ReCaptchaSiteKey");  
           string GoogleSecretKey = Configuration.Settings.GetSetting("ReCaptchaSecretKey");  
           if (!string.IsNullOrEmpty(GoogleSiteKey) && !string.IsNullOrEmpty(GoogleSecretKey))  
           {  
             SiteKey = GoogleSiteKey;  
             SecretKey = GoogleSecretKey;  
           }  
         }  
       }  
    

  • Create new CustomRecaptcha.cshtml file on this location “Website/Views/FormBuilder/FieldTemplates”
  •  @model <Path>.RecaptchaViewModel  
     <script src='https://www.google.com/recaptcha/api.js'></script>  
     <script>  
       $(document).ready(function () {  
         $('.recaptcha').click(function (e) {  
           var recaptchaResponse = grecaptcha.getResponse();  
           console.log(recaptchaResponse);  
           console.log(recaptchaResponse.length);  
           if (recaptchaResponse.length != 0) {  
             $('.googleRecaptchaClass').val(recaptchaResponse);  
           }  
         })  
       });  
     </script>  
     <span class="msg-error"></span>  
     <textarea id="@Html.IdFor(m => Model.Value)" class="googleRecaptchaClass" style="display:none;" name="@Html.NameFor(m => Model.Value)" data-sc-tracking="@Model.IsTrackingEnabled" data-sc-field-name="@Model.Name"></textarea>  
     <div class="g-recaptcha" data-sitekey="@Model.SiteKey"></div>  
    
  • Move to this location “Website/Views/FormBuilder/FieldTemplates” and open “Button.cshtm” and add “recaptcha” class in class attribute.
  • In the Sitecore Content Editor, navigate to /sitecore/templates/System/Forms/Fields 
  • Then add new template with name “CustomRecaptcha” and select Base template /sitecore/templates/System/Templates/Template
  • You can inherit template which is required
    Sitecore 9 Forms Google reCaptcha field
  • Switch to Core DB and create copy of this item “sitecore/client/Applications/FormsBuilder/Components/Layouts/PropertyGridForm/PageSettings/Settings/SingleLineText” with name “CustomRecaptcha”
  • Now move again to Master DB.
  • Create new Field type here “/sitecore/system/Settings/Forms/Field Types/Security” with name “CustomRecaptcha”
  • Fill below details:
    • View Path: FieldTemplates/CustomRecaptcha
    • Model Type:  <Namespace>. RecaptchaViewModel, <AssemblyName>
    • Property Editor: Property Editor Settings/CustomRecaptcha
    • Field Template: Fields/CustomRecaptcha

Custom reCaptcha Validation

  • Create new submit action class RecaptchaValidate
  •  public class RecaptchaValidate : SubmitActionBase<string>  
       {  
         /// <summary>  
         /// Initializes a new instance of the <see cref="LogSubmit"/> class.  
         /// </summary>  
         /// <param name="submitActionData">The submit action data.</param>  
         public RecaptchaValidate(ISubmitActionData submitActionData) : base(submitActionData)  
         {  
         }  
         /// <summary>  
         /// Tries to convert the specified <paramref name="value" /> to an instance of the specified target type.  
         /// </summary>  
         /// <param name="value">The value.</param>  
         /// <param name="target">The target object.</param>  
         /// <returns>  
         /// true if <paramref name="value" /> was converted successfully; otherwise, false.  
         /// </returns>  
         protected override bool TryParse(string value, out string target)  
         {  
           target = string.Empty;  
           return true;  
         }  
         /// <summary>  
         /// Executes the action with the specified <paramref name="data" />.  
         /// </summary>  
         /// <param name="data">The data.</param>  
         /// <param name="formSubmitContext">The form submit context.</param>  
         /// <returns>  
         ///  <c>true</c> if the action is executed correctly; otherwise <c>false</c>  
         /// </returns>  
         protected override bool Execute(string data, FormSubmitContext formSubmitContext)  
         {  
           if (!formSubmitContext.HasErrors)  
           {  
             RecaptchaViewModel googleRecaptchaFieldValue = formSubmitContext.Fields.Where(x => x is RecaptchaViewModel).FirstOrDefault() as RecaptchaViewModel;  
             if (googleRecaptchaFieldValue != null)  
             {  
               ISitecoreContext sitecoreContext = ServiceLocator.ServiceProvider.GetService<ISitecoreContext>();  
               var formSettings = sitecoreContext.GetItem<_FormSettings>(ItemIds.FormSettings);  
               if (formSettings != null && !string.IsNullOrEmpty(formSettings.SecretKey))  
               {  
                 bool isCapthcaValid = ValidateCaptcha(googleRecaptchaFieldValue.Value, formSettings.SecretKey.ToString());  
                 try  
                 {  
                   if (isCapthcaValid)  
                   {  
                     return true;  
                   }  
                 }  
                 catch  
                 {  
                   formSubmitContext.Abort();  
                   return false;  
                 }  
               }  
             }  
             formSubmitContext.Abort();  
             return false;  
           }  
           else  
           {  
             Logger.Warn(Invariant($"Form {formSubmitContext.FormId} submitted with errors: {string.Join(", ", formSubmitContext.Errors.Select(t => t.ErrorMessage))}."), this);  
           }  
           formSubmitContext.Abort();  
           return false;  
         }  
         public static bool ValidateCaptcha(string response, string secret)  
         {  
           string RecaptchaUrl = Configuration.Settings.GetSetting("GoogleApi");  
           var client = new WebClient();  
           var reply = client.DownloadString(RecaptchaUrl+"?secret=" + secret + "&response="+response);  
           var captchaResponse = JsonConvert.DeserializeObject<CaptchaResponse>(reply);  
           return System.Convert.ToBoolean(captchaResponse.Success);  
         }  
       }  
    
  • ItemIds.FormSettings is Sitecore item id which contains SecretKey field
  • For GoogleApi key create a patch file like below:

  •  <?xml version="1.0"?>  
     <configuration xmlns:patch="http://www.sitecore.net/xmlconfig/" xmlns:set="http://www.sitecore.net/xmlconfig/set/">  
      <sitecore>  
       <settings>  
        <setting name="GoogleApi" value="https://www.google.com/recaptcha/api/siteverify"/>  
       </settings>    
      </sitecore>  
     </configuration>  
  • Create CaptchaResponse class

  •   public class CaptchaResponse  
       {  
         [JsonProperty("success")]  
         public bool Success { get; set; }  
         [JsonProperty("error-codes")]  
         public List<string> ErrorMessage { get; set; }  
       }  
  • Go to this location “/sitecore/system/Settings/Forms/Submit Actions”
  • Create new submit action “Recaptcha Validate” using this template “/sitecore/templates/System/Forms/Submit Action”
  • Fill below details:
    • Model Type: <Path>.RecaptchaValidate
    • Error Message: Invalid Captcha
  • Now go to Sitecore Form Editor and you will see Custom Captcha control inside Security tab
Sitecore 9 Forms Google reCaptcha field

  • Drag and drop control into your form
Sitecore 9 Forms Google reCaptcha field

  • Do not forget to select “Recaptcha Validate” on your submit action
Sitecore 9 Forms Google reCaptcha field
  • Render form into your page and Enjoy


Comments

Anonymous said…
Hi Swati, thank you for a great article.

I am trying to implement Google ReCaptcha V3

I was able to implement following these steps. But I am facing just one issue. My Custom Submit Method is called twice and thus it results duplicate ReCaptcha verification.

I have placed by Custom Submit item before Save Data in the Forms design.

Could you please let me know what can be the issue? Any hints or response is much appreciated. Thank you.
Swati Gupta said…
Is this happening for every submit action or only for Recaptcha validate?
Unknown said…
Hi Swati. do you have any example for V3 Google Recaptcha ?
Swati Gupta said…
Not yet but surely I will create
Kamal said…
This comment has been removed by the author.
Kamal said…
Hi Swati, I am implementing hcaptcha in sitecore forms, in that I want a behaviour that once user clicks the submit button then it should shows up the captcha challenge to user and then form should get submit. Form is using ajax calls and formbuilder. Do you know what should I do here?

Popular posts from this blog

Sitecore 10.2 - “Failed to start service ‘Sitecore Marketing Automation Engine’” on Windows 11

Sitecore 10.2 - “Failed to start service ‘Sitecore Marketing Automation Engine' ” on Windows 11 Today I started to install Sitecore 10.2 using Sitecore Instance Manager on Windows 11 and I got this issue “Failed to start service ‘Sitecore Marketing Automation Engine' ” . Error : On event viewer it was showing the below error: I also tried to run ‘ Sitecore.MAEngine.exe ’ like this C:\Windows\system32>C:\inetpub\wwwroot\sclocal102xconnect.dev.local\App_Data\jobs\continuous\AutomationEngine\Sitecore.MAEngine.exe Which was throwing below error: Starting Marketing Automation Engine... 2022-01-29 22:21:11 ERR Error initializing XConnect client. System.AggregateException: One or more errors occurred. ---> Sitecore.XConnect.XdbCollectionUnavailableException: An error occurred while sending the request. ---> System.Net.Http.HttpRequestException: An error occurred while sending the request. ---> System.Net.WebException: The underlying connection was closed: An unexpected err

Azure AD Integration with Sitecore 10.2

 Azure AD Integration with Sitecore 10.2 Sitecore identity server that comes with Sitecore 9.1 allows you to log in through an external identity provider like Azure Active Directory, Facebook, Apple, or Google. It is built on Federation Authentication. What is Federation Authentication? Federation authentication is a technology to allows users to access multiples application, tools, and domains using one credential. Using one set of credential user can access multiple applications, and resources after authentication.  Federation authentication consists of two systems, the Identity provider and the Service provider. Identity providers that maintain/create/manage identity information like name, email address, device, and location. Some examples of identity providers are Azure AD, Google, Facebook, and Apple. Service providers basically refer to a website, software, or app that the user is trying to access and SP basically relies on the identity provider to authenticate the user and provi

Sitecore Custom API Issue with Federation Authentication

Sitecore Custom API Issue with Federation Authentication In earlier segments, detailed in Part 1 and Part 2 of the blogs on Keycloak Integration with Sitecore, I introduced Keycloak functionality for CM login. Concurrently, I addressed a necessity to develop custom APIs for retrieving Sitecore users and roles. Following the development of custom APIs, during authentication failures, the API erroneously returned a status code of 200 instead of 401. The problem arose because API requests were being routed through the "owin.identityProviders" pipeline, which was not intended for API usage. Solution: When OWIN identifies a 401 response and the AuthenticationMode is set to "Active," it fails to capture the URL hash included in the request. Another choice is to activate the "Passive" AuthenticationMode, wherein OWIN refrains from actively intercepting 401 responses. In passive mode, your application needs to explicitly issue a Challenge to trigger the OWIN aut