Implementing reCAPTCHA v3 on .NET Core & Angular: Ultimate Guide

In a world filled with bots, spammers, and cyber-criminals, website security has become a top priority for developers. And while there is a multitude of security measures you can take, implementing an invisible reCAPTCHA v3 in your .NET Core application can go a long way in keeping the bad guys at bay.

In this implementation guide, we’ll show you how to add this powerful tool to your application, without driving your users crazy with tedious “I am not a robot” tests. So, sit back, grab your favorite beverage, and get ready to secure your app like a pro (and have a laugh or two along the way)!

What is reCAPTCHA

If you’ve ever been filling out a form online and been asked to prove that you’re not a robot, chances are you’ve encountered the dreaded reCAPTCHA. At first, you might have thought, “Oh, great, another thing to slow me down.” But fear not, dear internet user! reCAPTCHA is actually a pretty nifty invention.

In short, reCAPTCHA is a security tool used to protect websites from spam and abuse. It works by presenting the user with a challenge, usually in the form of distorted text or images, and asking them to prove they’re human by typing in what they see. It’s like a digital game of “I Spy,” but instead of finding objects in a picture, you’re trying to decipher letters that look like they’ve been run through a blender.

But why do we need reCAPTCHA in the first place? Well, as it turns out, there are a lot of robots out there that want to wreak havoc on the internet. And no, I’m not talking about the cute little Roombas that clean your floors. I’m talking about malicious software that can be programmed to fill out forms, create fake accounts, and basically just make a nuisance of itself. reCAPTCHA helps prevent these bots from doing their dirty work by making sure that the only ones filling out forms are real, live humans.

Of course, reCAPTCHA isn’t foolproof. Some humans might struggle to read distorted text or images, while some bots might be smart enough to figure out the answer. But overall, it’s a pretty effective tool for keeping the internet safe and spam-free.

So the next time you encounter a reCAPTCHA challenge, don’t roll your eyes and curse the internet gods. Just think of it as a fun little game, and take pride in the fact that you’re helping to keep the online world a little bit safer.

Differences between reCAPTCHA v2 and reCAPTCHA v3

Ah, reCAPTCHA. The bane of every internet user’s existence. But don’t worry, my friend. With the release of reCAPTCHA v3, things might be looking up. But what exactly is the difference between v2 and v3? Let’s break it down.

First of all, let’s talk about the OG, reCAPTCHA v2. You know it, you love it (okay, maybe you don’t love it), and you’ve definitely encountered it before. This version of reCAPTCHA works by presenting the user with a challenge, like distorted text or images, and asking them to prove they’re human by typing in what they see. The catch? The challenges can be pretty darn tricky to decipher, especially if you’re in a rush or just not in the mood to play a game of “I Spy”.

Enter reCAPTCHA v3. This version is a bit more behind-the-scenes. Instead of presenting the user with a challenge, it works by analyzing the user’s behavior on the site and assigning a “score” based on how likely they are to be a bot. So if you’re behaving like a normal human being (clicking on links, filling out forms, scrolling through pages, etc.), you’ll get a high score and won’t be bothered with any additional challenges. But if you’re exhibiting suspicious behavior (like clicking on every link on the page in the span of five seconds), you might get a lower score and be asked to prove you’re human with a challenge.

So what’s the difference between these two versions, besides the obvious challenge vs. no challenge aspect? Well, reCAPTCHA v3 is supposed to be more user-friendly, since you don’t have to go through the hassle of deciphering distorted text or images. It’s also supposed to be more effective at detecting bots since it’s analyzing behavior in real-time rather than relying on the user to prove they’re human.

But of course, nothing is perfect. Some users might prefer the challenge-based approach of v2, while others might find v3 to be too invasive. And who knows, maybe the bots will catch up to v3 eventually and start behaving like real humans. Until then, we’ll just have to keep playing our little games of “I Spy” and “I’m Not a Robot”. Hey, at least it makes for some good entertainment, right?

If you want to find out how to use reCAPTCHA v2 in your .NET Core and Angular applications I wrote an article about it. How To Use Google ReCAPTCHA V2 With .NET Core .

reCAPTCHA v3 with .NET Core Web API

In this step-by-step tutorial, I’ll walk you through the process of integrating reCAPTCHA v3 into your .NET Core Web API, so you can sit back, relax, and let the robots be robots. Let’s get started!

  1. We start by creating a new service where we validate the token received from reCAPTCHA
public class RecaptchaV3Service : IRecaptchaV3Service
    {
        private readonly IConfiguration configuration;
        private readonly IHttpClientFactory httpClientFactory;
        public RecaptchaV3Service(IConfiguration configuration, IHttpClientFactory httpClientFactory)
        {
            this.configuration = configuration;
            this.httpClientFactory = httpClientFactory;
        }
        public async Task<bool> ValidateReCaptchaResponse(string response)
        {
            var httpRequestMessage = new HttpRequestMessage(
            HttpMethod.Get,
            string.Format(configuration.GetSection("Authentication:ReCaptcha:v3:Url").Get<string>(),
                configuration.GetSection("Authentication:ReCaptcha:v3:PrivateKey").Get<string>(), response));
            var httpClient = httpClientFactory.CreateClient();
            try
            {
                var httpResponseMessage = await httpClient.SendAsync(httpRequestMessage);
                if (httpResponseMessage.IsSuccessStatusCode)
                {
                    using var contentStream = await httpResponseMessage.Content.ReadAsStreamAsync();
                    using (var readStream = new StreamReader(contentStream))
                    {
                        var jsonResponse = readStream.ReadToEnd();
                        var data = JsonConvert.DeserializeObject<RecaptchaV3Response>(jsonResponse);
                        return data.Success && data.Score >= 0.5;
                    }
                }
                return false;
            }
            catch (WebException)
            {
                return false;
            }
        }
    }

ValidateReCaptchaResponse receives the token and validates it towards reCAPTCHA API. The secret key and the URL for the API are stored in appsettings.json file.

{
 
    "ReCaptcha": {
      …,
      "V3": {
        "Url": "https://www.google.com/recaptcha/api/siteverify?secret={0}&response={1}",
        "PrivateKey": "--Recaptcha Private Key--"
      }
    }
  },

}

The response from reCAPTCHA API is being deserialized based on this model:

public class RecaptchaV3Response
    {
        [JsonProperty("success")]
        public bool Success { get; set; }
        [JsonProperty("score")]
        public float Score { get; set; }
        [JsonProperty("action")]
        public string Action { get; set; }
        [JsonProperty("challenge_ts")]
        public DateTime ChallengeTs { get; set; }
        [JsonProperty("hostname")]
        public string HostName { get; set; }
        [JsonProperty("error-codes")]
        public string[] ErrorCodes { get; set; }
    }
  1. Now that we have the service and the model we can go ahead and use them from our business layer like this:
if (!await recaptchaV3Service.ValidateReCaptchaResponse(loginCredentials.Recaptcha))
            {
                throw new ApplicationException("Please validate ReCaptcha!");
            }

If the reCAPTCHA service is not able to validate the token it will return false and we will throw an exception that will end-up being shown on the client side.

You can find the source code by following the Identity Microservice source code URL from the resources section above.

reCAPTCHA v3 in an Angular App

In this example, the UI part of our application is created using Angular 2+ and Angular Material. Let’s see what should we do to have reCAPTCHA v3 integrated with our app.

  1. Install ng-recaptcha:
npm i ng-recaptcha --save
  1. Import RecaptchaV3Module into your modules file
  2. Register the v3 provider into the same modules file
Import RecaptchaV3Module into your modules file
Register the v3 provider into the same modules file
  1. Use reCAPTCHA v3 where needed like this:
import { RecaptchaComponent, ReCaptchaV3Service } from 'ng-recaptcha';
...
constructor(...
    private recaptchaV3Service: ReCaptchaV3Service,) {
...
this.recaptchaV3Service.execute('key-of-your-choice')
      .subscribe((token) => {
...

The key you provide in this step can be validated in the backend as well, using the “Action” field received from Google reCAPTCHA API.

If you think I might have missed something about how to integrate ng-recaptcha, go ahead and check the official npm page https://npmjs.com/package/ng-recaptcha .

If you want to see the reCAPTCHA v3 in action you can check out the Login and Register components from the Angular Identity application. Just follow the URLs below and check out that code.

Resources

Conclusions

And that’s a wrap, folks! You’ve reached the end of our implementation guide for securing your .NET Core application with invisible reCAPTCHA v3. By now, you should be feeling like a website security superhero, ready to thwart any bots or spammers that come your way. But remember, with great power comes great responsibility.

Stay moderate with reCAPTCHA, or you might risk alienating your users (and we all know how that ends… in tears and low website traffic). Use it wisely, and your users will thank you for keeping their data safe and sound. So go forth, my fellow developers, and secure those apps like the pros you are (and don’t forget to grab a well-deserved snack while you’re at it)!