Skip to main content

Captcha

Overview

Captcha is a way how to secure APIs against bots interactions. The security consists from front end and backend verification where frontend is requesting token from Captcha provider and is providing the token to backend service which validates the token against same Captcha provider.

We are using reCaptcha V3. reCAPTCHA v3 returns a score for each request without user friction. The score is based on interactions with your site and enables you to take an appropriate action for your site.

Frontend documentation - For the Angular documentation, please look here: Captcha integration

Install

Dependencies:

.Net backend integration

First setup

Nuget package: ASOL.Core.ApiController

  1. Add secret key to the appsettings.json
"GoogleReCaptchaOptions": {
"SecretKey": "#{Recaptcha_SecretKey}#",
"SuppressCaptchaValidatorUrl": "https://#{Dns_AsolAppWebSite}#:44322/api/v1/CaptchaStatus",
"Actions": {
"Register": { // The custom name of the action, see the second parameter in the ValidateUserScoreAsync method in the example in the Usage section below.
"MinScore": 0.5
}
}
}
  1. At startup.cs in the method ConfigureServices add
services.Configure<GoogleReCaptchaOptions>(Configuration.GetSection("GoogleReCaptchaOptions"));
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.

Backend usage

  1. In backend controller add to DI parameter to constructor: ICaptchaValidator captchaValidator
  2. In backend controller in method:
[HttpPost]
[AllowAnonymous]
[Route("register")]
[ProducesResponseType(StatusCodes.Status202Accepted)]
[ProducesResponseType(StatusCodes.Status400BadRequest, Type = typeof(ValidationProblemDetails))]
public async Task<IActionResult> RegisterAsync([FromBody] RegisterModel model)
{
// handle captcha validation include suppress validation logic for action "Register"
if (!await _captchaValidator.ValidateUserScoreAsync(model.Captcha, "Register"))
{
// throw exception with Captcha validation reponse body
return this.CaptchaError();
}
// Do the processing controller method logic. Captcha is ok, requester is almost certainly human.
return await DoRegisterAsync(model, CancellationToken.None);
}

This method is using success validation only and does not handle score. That is it the captcha should be working.