Implementing Google's reCapcha v3 to ASP.NET Core 3 project
Tags: dotnet, csharp, captcha, tutorial
Published: 2019-11-05 13:15:27

In this tutorial, you will get know how to properly use Google's reCaptcha in your .NET Core 3 projects.

First, you have to register your site there https://www.google.com/recaptcha/admin
if you are debugging at localhost don't forget to add localhost as the URL as well.

After registring, you get your keys. The site key and the secret key.
the site key is visible to others and its used to call js library hosted on google's server
https://www.google.com/recaptcha/api.js?render=SITE_KEY

Secret key is used on backend for validating requests and getting result (was the  form sent by human or bot)


Once you got your keys, you are ready to implement reCaptcha to your project.
Install the following nuget package to your project https://www.nuget.org/packages/GoogleReCaptcha.V3/

Add keys to the appsettings.json

    "googleReCaptcha:SiteKey": "_YOUR_SITE_KEY",
    "googleReCaptcha:SecretKey": "YOUR_SECRET_KEY",

The package contains an class which has to be registred using middleware.

At startup.cs
in the method 

    public void ConfigureServices(IServiceCollection services)

add following

    public void ConfigureServices(IServiceCollection services)
    {
       services.AddControllersWithViews();

       services.AddHttpClient<ICaptchaValidator, GoogleReCaptchaValidator>();
    }

This row added captcha class to DI and allow us to inject it to controllers.
Class requires HTTP comunication with Google's server so it was registred as a HttpClient. It causes to use HttpClient provider to open communication, not the wrong way to open always a new socket.

Now it is time to prepare your form which needs to be protected from BOTs. All you have to do is shown bellow. Just inject the configuration to access your SITE_KEY. Add hidden input for token and add the block of javascript to inlcude Google's library and set proper ID of input for token.

    @inject Microsoft.Extensions.Configuration.IConfiguration Configuration
    @model SampleViewModel
    @{
        ViewData["Title"] = "Home Page";
    }
    <h1>@ViewData["Message"]</h1>
    <div class="row">
        <div class="col-md-4">
            <form method="post" asp-action="Index">
                <input type="hidden" name="captcha" id="captchaInput" />
                <div class="form-group">
                    <label asp-for="Text"></label>
                    <input asp-for="Text" class="form-control"/>
                    <span asp-validation-for="Text" class="text-danger"></span>
                </div>
                <div class="form-group">
                    <input type="submit" value="Submit" class="btn btn-primary"/>
                </div>
            </form>
        </div>
    </div> 
    @section Scripts
    {
        <script src="https://www.google.com/recaptcha/api.js?render=@Configuration["googleReCaptcha:SiteKey"]"></script>
        <script>
            grecaptcha.ready(function() {
                window.grecaptcha.execute('@Configuration["googleReCaptcha:SiteKey"]', { action: 'home' }).then(function (token) {
                    $("#captchaInput").val(token);
                });
            });
        </script>
    }

Now the last part is backend validation. The first inject the validation object to your controller:

    public class HomeController : Controller
    {
        private readonly ICaptchaValidator _captchaValidator;

        public HomeController(ICaptchaValidator captchaValidator)
        {
            _captchaValidator = captchaValidator;
        }

And use the object to validate the form

    [HttpPost]
    public async Task<IActionResult> Index(SampleViewModel collection, string captcha)
    {
       if (!await _captchaValidator.IsCaptchaPassedAsync(captcha))
       {
          ModelState.AddModelError("captcha","Captcha validation failed");
       }
       if(ModelState.IsValid)
       {
          ViewData["Message"] = "Success";
       }
       return View(collection);
    }

Thats all you have to do to implement the latest Google's reCaptcha v3 :)

Stay updated https://github.com/Jarda29/GoogleReCaptcha.V3