meta info
- Title: Asp.Net Core - Install Google reCAPTCHA v3
- Keywords: asp.net, core, google, recaptcha, security
- Description: How to install google reCAPTCHA v3 on Asp.Net Core project using backend validiation.
- Author: Ziya Mollamahmut
- Date: 18-Mar-2021
- Image: https://github.com/LazZiya/Docs/raw/master/Miscellaneous/v1.0/images/ziya-logo.png
- Image-alt: Miscellaneous Logo
- Version: v1.0
How to protect user login with google reCAPTCHA v3 programmatically in Asp.Net Core projects. reCAPTCHA usage is already explained in google docs, but here I will explain how to use it with Asp.Net Core login page.
Basically, we will use reCAPTCHA where we do post from pages like Login
that are accessible to anonymous users and bots. So, in this sample I will use Login
page for demonstration, but this can be applied to any similar page like reset password and registration pages as well.
-
Goto your google reCAPTCHA admin page and register a new site:
-
Copy the site key and secret key
Put the site key and secret key in user secrets file:
"GoogleReCAPTCHAv3": {
"SiteKey": "MY-SITE-KEY",
"SecretKey": "MY-SECRET-KEY"
}
It is recommended to store passwords and keys in a secure place, but using appsettings.json also can work for testing purpose.
- Create a new client service that will connect to the reCAPTCHA API's and do valdiation in the backend, this service will use the
SecretKey
and Token for validation.
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json.Linq;
using System;
using System.Net;
using System.Net.Http;
using System.Net.Sockets;
using System.Threading.Tasks;
namespace GoogleReCaptchaV3
{
public class ReCaptchaService
{
private readonly HttpClient _client;
private readonly ILogger _log;
private readonly string _secretKey;
public ReCaptchaService(
HttpClient httpClient,
ILogger<ReCaptchaService> logger,
IConfiguration configuration)
{
_log = logger;
_client = httpClient ?? throw new NullReferenceException(nameof(httpClient));
_client.BaseAddress = new Uri("https://www.google.com");
_secretKey = configuration.GetValue<string>("GoogleReCAPTCHAv3:SecretKey")
?? throw new NullReferenceException("GoogleReCAPTCHAv3:SecretKey");
}
public async Task<bool?> ValidateReCaptchaAsync(string token)
{
try
{
var response = await _client.GetAsync($"/recaptcha/api/siteverify?secret={_secretKey}&response={token}");
if (response.StatusCode != HttpStatusCode.OK)
return false;
string JSONresponse = await response.Content.ReadAsStringAsync();
dynamic JSONdata = JObject.Parse(JSONresponse);
if (JSONdata.success != "true")
return false;
}
catch (SocketException e)
{
_log.LogCritical("CAN'T CONNECT TO GOOGLE CAPTCHA SERVER!");
_log.LogError(e.Message);
return null;
}
catch (HttpRequestException e)
{
_log.LogCritical("CAN'T CONNECT TO GOOGLE CAPTCHA SERVER!");
_log.LogError(e.Message);
return null;
}
return true;
}
}
}
- Register the reCAPTCHA service in startup:
services.AddHttpClient<ReCaptchaServics>();
In the backend we will get the SiteKey
from user secrets file, and then we will validate the token using our newely created service.
[AllowAnonymous]
public class LoginModel : PageModel
{
private readonly ReCaptchaService _captcha;
public readonly string SiteKey;
// ... other services
// the token will be generated by google reCAPTCHA API js call
// add as relevant script and filed in the login form
[FromForm]
public string Token { get; set; }
public LoginModel(ReCaptchaService captcha,
IConfiguration configuration,
// ... other services
)
{
_captcha = captcha;
// get SiteKey from user secrets
SiteKey = configuration.GetValue<string>("GoogleReCAPTCHAv3:SiteKey");
}
// Do captcha valdiation before model validiation
public async Task<IActionResult> OnPostAsync(string returnUrl = null)
{
returnUrl ??= Url.Content("~/");
var captchaChallenge = await _captcha.ValidateReCaptchaAsync(Token);
if (captchaChallenge == null)
{
// reCAPTCHA validiation is not possible
// could be a connection problem
_log.LogCritical("Can't connect to reCAPTCHA servers");
return Page();
}
else if (!captchaChallenge.Value)
{
_log.LogWarning("You didn't pass the reCAPTCHA challenge!");
return Page();
}
// if we get here, so far we passed the reCAPTCHA challenge :)
// .. rest of the code
}
}
- Here we need to add additonal
Token
field to the login form:
<input type="hidden" asp-for="Token" />
The token value will be generated by google reCAPTCHA API through below js code:
<!-- Google ReCAPTCHA.V3-->
<script src="https://www.google.com/recaptcha/api.js?render=@Model.SiteKey"></script>
<script>
grecaptcha.ready(function () {
grecaptcha.execute('@Model.SiteKey', { action: 'homepage' }).then(function (token) {
document.getElementById("Token").value = token;
});
});
</script>
https://github.com/LazZiya/BlogSamples/tree/master/GoogleReCaptchaV3