♻️ A minimal, no-drama, friction-less C# HTTP verification client for Google's reCAPTCHA API.
The problem with current ReCaptcha libraries in .NET is that all of them take a hard dependency on the underlying web framework like ASP.NET WebForms, ASP.NET MVC 5, ASP.NET Core, or ASP.NET Razor Pages.
Furthermore, current reCAPTCHA libraries for .NET are hard coded against the HttpContext.Request
to retrieve the remote IP address of the visitor. Unfortunately, this method doesn't work if your website is behind a service like CloudFlare where the CF-Connecting-IP
header value is the real IP address of the visitor on your site.
BitArmory.ReCaptcha is a minimal library that works across all .NET web frameworks without taking a hard dependency on any web framework. If you want to leverage platform specific features, like MVC Action Filters, you'll need to implement your own ActionFilter
that leverages the functionality in this library.
- .NET Standard 1.3 or later
- .NET Framework 4.5 or later
- 🐕 Dogecoin:
DGVC2drEMt41sEzEHSsiE3VTrgsQxGn5qe
Nuget Package BitArmory.ReCaptcha
Install-Package BitArmory.ReCaptcha
You'll need to create reCAPTCHA account. You can sign up here! After you sign up and setup your domain, you'll have two important pieces of information:
- Your
site
key - Your
secret
key
This library both reCAPTCHA v2 and reCAPTCHA v3.
Be sure to checkout this video that describes how reCAPTCHA v3 works before implementing.
Then, on every page of your website, add the following JavaScript:
<html>
<head>
<script src='https://www.google.com/recaptcha/api.js?render=GOOGLE_SITE_KEY'></script>
</head>
<body>
...
<script>
grecaptcha.ready(function() {
grecaptcha.execute('GOOGLE_SITE_KEY', {action: 'TAG'});
});
</script>
</body>
</html>
Every page should call grecaptcha.execute
with some unique action TAG
. Read more about actions in the official docs here. When it's time to validate an HTTP POST
you'll need to do the following:
<html>
<body>
<form action='/do-post' method='POST'>
<input id="captcha" type="hidden" name="captcha" value="" />
</form>
<script>
grecaptcha.ready(function() {
grecaptcha.execute('GOOGLE_SITE_KEY', {action: 'SOME_ACTION'})
.then(function(token) {
// Set `token` in a hidden form input.
$("#captcha").val(token);
});
});
</script>
</body>
</html>
When the POST
is received on the server:
- Get the client's IP address. If you're using CloudFlare, be sure to use the
CF-Connecting-IP
header value. - Extract the
#captcha
value (client token) in the hidden HTML form field. - Use the
ReCaptchaService
to verify the client's reCAPTCHA is valid.
//1. Get the client IP address in your chosen web framework
string clientIp = this.HttpContext.Connection.RemoteIpAddress.ToString();
string token = null;
string secret = "your_secret_key";
//2. Extract the `#captcha` field from the hidden HTML form in your chosen web framework
if( this.Request.Form.TryGetValue("captcha", out var formField) )
{
token = formField;
}
//3. Validate the reCAPTCHA with Google
var captchaApi = new ReCaptchaService();
var result = await captchaApi.Verify3Async(token, clientIp, secret);
if( !result.IsSuccess || result.Action != "SOME_ACTION" || result.Score < 0.5 )
{
// The POST is not valid
return new BadRequestResult();
}
else{
//continue processing, everything is okay!
}
You'll want to make sure the action name you choose for the reuqest is legitmate. The result.score
is the probably of a human. So, you'll want to make sure you have a result.Score > 0.5
; anything less is probably a bot.
Add the following <div class="g-recaptcha">
and <script>
tags to your HTML form:
<html>
<body>
<form method="POST">
...
<div class="g-recaptcha" data-sitekey="your_site_key"></div>
<input type="submit" value="Submit">
</form>
<script src="https://www.google.com/recaptcha/api.js" async defer></script>
</body>
</html>
When the POST
is received on the server:
- Get the client's IP address. If you're using CloudFlare, be sure to use the
CF-Connecting-IP
header value. - Extract the
g-recaptcha-response
(Client Response) HTML form field. - Use the
ReCaptchaService
to verify the client's reCAPTCHA is valid.
The following example shows how to verify the captcha during an HTTP POST
back in ASP.NET Core: Razor Pages.
//1. Get the client IP address in your chosen web framework
string clientIp = this.HttpContext.Connection.RemoteIpAddress.ToString();
string captchaResponse = null;
string secret = "your_secret_key";
//2. Extract the `g-recaptcha-response` field from the HTML form in your chosen web framework
if( this.Request.Form.TryGetValue(Constants.ClientResponseKey, out var formField) )
{
capthcaResponse = formField;
}
//3. Validate the reCAPTCHA with Google
var captchaApi = new ReCaptchaService();
var isValid = await captchaApi.Verify2Async(capthcaResponse, clientIp, secret);
if( !isValid )
{
this.ModelState.AddModelError("captcha", "The reCAPTCHA is not valid.");
return new BadRequestResult();
}
else{
//continue processing, everything is okay!
}
That's it! Happy verifying! 🎉
- Download the source code.
- Run
build.cmd
.
Upon successful build, the results will be in the \__compile
directory. If you want to build NuGet packages, run build.cmd pack
and the NuGet packages will be in __package
.