How To Implement Google reCAPTCHA v3 in Flutter Web

Zujaj Misbah Khan
Level Up Coding
Published in
6 min readDec 19, 2021

--

A Basic Guide to Developers for embedding the Google reCAPTCHA v3 in Flutter Web.

Depiction of Bot Attack on a Web Form.
Depiction of Bot Attack on a Web Form.

THE FEAR OF BOT

As a developer, whenever you create forms to get the data from a user on the web, you always need to be alert from spam data. Hackers can inject scripted bots to fill the form with malicious code activity and access your site’s backend.

Google introduced the concept of reCAPTCHA, a free and secure service¹ to handle the fear of bots. From the website, it states that

reCAPTCHA v3 helps you detect abusive traffic on your website without user interaction. Instead of showing a CAPTCHA challenge, reCAPTCHA v3 returns a score so you can choose the most appropriate action for your website.

CLIENT SIDE SETUP

Before start coding, you would need to register the site on which the reCAPTCHA v3 would be used. Follow the below steps:

  1. Visit the Google reCAPTCHA site , click on “v3 Admin Console” & sign in with your Google account.
Illustration of Google reCAPTCHA v3 Admin Console Navigation.
Illustration of Google reCAPTCHA v3 Admin Console Navigation.

2. Select “reCAPTCHA v3” and type “localhost ” (if you’re not ready for a production environment), accept the terms & hit the “Submit” button.

Illustration of Google reCAPTCHA v3 Site Registration Form.
Illustration of Google reCAPTCHA v3 Site Registration Form.

3. After successful registration, note down the reCAPTCHA site & secret keys.

Illustration of Google reCAPTCHA v3 Site and Secret Keys.
Illustration of Google reCAPTCHA v3 Site and Secret Keys.

REQUIRED PUBSPEC PACKAGES

In the pubspec.yaml file, add the below packages under dependencies .

Required Packages in Pubspec.yaml file

THE BIG PICTURE

For the sake of simplicity, we will be creating a MaterialApp having a bear bone Formwidget with a “Name” TextFormField and aSubmit button, see Figure-I for the app widget tree structure.

Figure-I : Illustration of the App Widget Tree.
Figure-I : Illustration of the App Widget Tree.

As shown in Figure-II, from the client perspective, we would need to:

  1. Make the mainmethod asynchronous.
  2. Inside main, call the GRecaptchaV3.ready² method before runApp.
  3. On hitting submit, invoke the GRecaptchaV3.execute² method.
  4. Save the generated “User Response Token” in a private variable _token.
Figure-II : Illustration of the Client Side Flow.
Figure-II : Illustration of the Client Side Flow.

The client (our app) will send the _token with the recaptcha-secret-key as an HTTP POST Request to the server, as depicted in Figure-III.

Figure-III : Illustration of the Client-Server Flow.
Figure-III : Illustration of the Client-Server Flow.

Upon receiving the HTTP POST Request, the server validates the client’s request as depicted in Figure-IV. In this response, a scorebetween 0.0 to 1.0 is obtained where zero means no human interaction was found. We can say that “It’s likely a bot!” in terms of a layman³.

Figure-IV : Illustration of the Server-Client Flow.
Figure-IV : Illustration of the Server-Client Flow.

Depending on the nature of the site, we would define an actionand a threshold value which would interpret the obtained score. For more information regarding score interpretation & action , refer to the reCAPTCHA documentation³.

WORKAROUND TO HANDLE CORS IN FLUTTER WEB

Because we would be making HTTP requests through out the project, you might face CORS⁴ error in Flutter Web. Below is a work-around on Stack Overflow that would assist you make request in localhost.

LET’S START CODING!

WROOM! WROOM! WROOM! Hold on your keys because we are about to start coding. Below Figure-V shows the folder structure that would be maintained through out this project.

Figure-V: Illustration of the Project Architecture.
Figure-V: Illustration of the Project Architecture.

Step 1 - Place the reCAPTCHA Site Key in index.html file.

Navigate to the web folder, open the index.htmlfile and paste the below script inside the <body> tag as shown below.

Placement of reCAPTCHA Site Key in index.html

To check whether the Google reCAPTCHA v3 is working correctly on our site, invoke the GRecaptchaV3.ready method inmain.dartas shown in below snippet.

Testing Google reCAPTCHA v3 using main.dart

After running the above code, you would see the “protected by reCAPTCHA” as shown in Figure-VI below.

Figure-VI : Illustration of Counter App with Google reCAPTCHA protection.
Figure-VI : Illustration of Counter App with Google reCAPTCHA protection.

Step 2 - Securing The Confidential Information.

To keep the secret key & site key confidential, under the lib folder create a config folder with config.dart file as shown below in the code snippet. Note: Don’t forget to add this to the .gitignore file!

Code Snippet for config.dart

Step 3 - Create a ReCAPTCHA Response Model.

Under the lib folder create a model folder with recaptcha_response.dart file, as shown below in the code snippet. This class would hold the HTTP Response obtained as a dart object.

The Recaptcha Response Model.

Step 4 - Create a ReCAPTCHA Service.

Rather than directly invoking the GRecaptchaV3 methods, we create a Service Layer or a Wrapper class that would hold all the reCAPTCHAoperations.

The Recaptcha Service.

Let’s understand the code by breaking it up apart.

Replace GRecaptchV3.ready with RecaptchaService.initiate in main.dart
  1. RecaptchaService.initiate(): A wrapper for GRecaptchaV3.ready that would be used in the main method before running our app. As stated in the reCAPTCHAdocs, it is essential to call the readymethod before the executemethod, see above snippet.
  2. RecaptchaService.isNotABot(): It is invoked after the user submits the form & the submission passes all the validations. It’s a simple method which calculates the threshold value and returns true/false based upon the _score.
  3. RecaptchaService._getVerificationResponse(): A private method that performs HTTP POST request to verify the client’s response token. TheGRecaptchaV3.executemethod returns a response token which is valid for two seconds. To make a valid HTTP POST request, we would check that we first receive the response token, then pass it as a POST request body parameter along with the reCAPTCHA secret key. If the HTTP POST request succeeds, we would convert the HTTP Response to the RecaptchaResponsemodel object and return it.

Step 5 - Invoke the ReCAPTCHA Service After Form Submission.

Use of RecaptchaService.isNotABot method on Submit Button.

On the Submit button’s onPressed function, we would:

  1. Check that the GlobalKey<FormState> current state is validated. If it’s valid then proceed to step 2, else tell the user to fill the NameFormField properly.
  2. In case of success, invoke RecaptchaService.isNotABot()and assign it’s value to a boolean flag_isNotABot .
  3. Depending on the value of _isNotABot, show a dialog to the user.

Step 6 - Run the app

Run the app to see the results as shown in Figure-VII.

Figure-VII: Demo of the Google reCAPTCHA v3 in Flutter Web.
Figure-VII: Demo of the Google reCAPTCHA v3 in Flutter Web.

Visit the recaptcha_v3_tutorial⁵ GitHub Repository for the full source code of this project.

Tip - Type 1sif you wish to see the repo as in VSCode within the browser like https://github1s.com/Zujaj/recaptcha_v3_tutorial.

Google reCAPTCHA Admin Console

Illustration of the Google reCAPTCHA v3 Admin Console.
Illustration of the Google reCAPTCHA v3 Admin Console.

Visit the Google reCAPTCHA Admin console for risk analysis. Kindly note that the readings of localhost would differ as compared to a live hosted site. Once you’re ready for production, don’t forget to change your domain from “localhost” via the Admin Console’s ⚙️ Settings Icon.

CONCLUSION

I hope this article has been fruitful in guiding you towards the safety of your web forms in Flutter Web. If you enjoyed this article, don’t press the clap button once; press it 50 times!

ACKNOWLEDGEMENT

Thanks to the Level Up Coding platform for providing me the space to learn, explore and share this precious knowledge amongst the community of Flutter Developers. I am also thankful to Muzzammil-Khan from Telic Solutions for guiding me towards the Google reCAPTCHA v3 console.

Special thanks to Bharathraj for introducing the g_recaptcha_v3 package.

REFERENCES

[1]: About Google reCAPTCHA
https://www.google.com/recaptcha/about

[2]: g_recaptcha_v3 | Flutter Package
https://pub.dev/packages/g_recaptcha_v3

[3]: Interpreting The Score | reCAPTCHA Docs
https://developers.google.com/recaptcha/docs/v3#interpreting_the_score

[4]: Cross-Origin Resource Sharing (CORS) — HTTP | MDN (mozilla.org)
https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS

[5]: reCAPTCHA v3 Tutorial | GitHub Repository
https://github.com/Zujaj/recaptcha_v3_tutorial

--

--

A passionate flutter developer who loves to learn, explore and share knowledge. Serving at https://telicsolutions.com/