- Utilizes advanced risk analysis techniques to detect fraud.
- protect your websites or mobile applications from fraudulent activities and security risks such as:
- Spam.
- Abuse.
- Credential stuffing1.
- Account takeover (ATO).
- Automated account creation.
- Password breach.
- Leak detection.
- It has:
- Mobile app SDKs.
- Multi-factor authentication (MFA).
- It interacts with your:
- Backend.
- Clients (web pages or mobile applications).
- Client loads the web page.
- Client app initializes the reCAPTCHA JS API or mobile SDK.
- End user triggers an action protected by reCAPTCHA (e.g. login), the reCAPTCHA JS API or the mobile SDK in the client requests a verdict2 from reCAPTCHA.
- Get back an encrypted reCAPTCHA token (save it somewhere since we're gonna need it).
- Client sends the aforementioned token to backend.
- Backend sends an assessment req to reCAPTCHA + encrypted token.
- Backend receives a verdict score from ranging 0 to 1 + a reason code based on this request made to the backend.
- Now you can decide to reject the req or process it.
- On websites.
- On mobile apps.
- On the WAF layer.
-
Create a new project or use an existing one.
-
Enable the "reCAPTCHA Enterprise API".
-
Create a new "reCAPTCHA key" there by going to "reCAPTCHA" tab.
-
Pick a name for the key.
-
Choose your platform, in my case "Website".
-
Add your domain name, no port number, or protocol is allowed.
[!TIP]
If you're like me and want to just test it you can write:
localhost
or127.0.0.1
, or you can add both :).
-
-
Add the script tag in the key details page, "Integration" tag to your web app.
[!NOTE]
It is normal for your client to be able to see your reCAPTCHA key in plain text So do not worry about it. It is not supposed to be a secret ;).
-
Call the
grecaptcha.execute
function on whatever action you want to protect. In my case on clicking on "Sign up!" button.I do not like to have bots as user :kidding:. Anyway here is a break down on what you need to do:
- I created my registration form. It is called
register.html
and made the most beautiful UI.[!IMPORTANT]
The most important part is where I added a hidden
input
. That's how I am sending the token I got from Google reCAPTCHA service to my backend. - I wrote all the logics that I were not able to implement in htmx in what they call it hypermedia friendly in a separate JS file called
register.js
and linked it to my html file.- There we have a function called
isGoogleRecaptchaReady
which is responsible to check whether the Google's lib for reCAPTCHA is loaded. I just promisified it for the sake of syntax. - I realized that there are a couple of ways to modify a request before sending it:
- Through:
hx-on:htmx:config-request
attribute. But as you can see it is designed for simple scenarios and not for cases like our case where we need more room to work (learn more here). hx-sync
which looked it might be able to help me in one way or another but the more I looked at it the more I realized that it was not up to the task. You can have more complex logic in it but it won't wait until it is resolved and then make the forms request (learn more in their doc).
So here is what I was trying to do with it but could not.
I added an
hx-click
(in fact I tried firstonclick
but they where not any different). And inside that handler I tried to do the logic that I've implemented in step 3. - Through:
- I defined a listener for
htmx:confirm
event and inside it:- Made sure that we've intercepted the right event, the one that user is trying to register --
isRegisterForm
. - Then made sure Google's lib is ready --
isGoogleRecaptchaReady
. - Called Google's API with our site key to get a token for this request:
grecaptcha.enterprise.execute
. - Then updated our hidden input with the fetched value from Google.
[!CAUTION]
Here my hidden
input
did not have anyhx-*
attribute on it. Thus I did not need to tell htmx anything about me changing the DOM with JS. But if you have please note that:If javascript adds content to the DOM that has htmx attributes on it, you need to make sure that this content is initialized with the
htmx.process()
function.— Ref.
- Told htmx to send the req:
event.detail.issueRequest
.
- Made sure that we've intercepted the right event, the one that user is trying to register --
- There we have a function called
- I created my registration form. It is called
-
Add reCAPTCHA to your backend:
-
I have created a utility function called
createAssessment
, in it we are:[!CAUTION]
You need to either send your API key for authentication or can use a simpler approach called ADC which stands for Application Default Credentials. And here I decided to use API keys. But you can definitely go with what suits you're requirements most.
On a side note, not every API can be called with API keys. But we know for sure that create assessment can be called based on what is written here. And to learn about how you can create a new API key read this doc.
- Creating a client --
new RecaptchaEnterpriseServiceClient()
. - Constructing our request --
projectPath
, andrequest
variables. - Sending the req to get a score for the user action --
client.createAssessment
. - Performing some verifications before returning the
score
--isTokenValid
,isTheExpectedAction
, andisNumeric
. - Lastly we are closing the open connection we've created just a few steps ago (step #1).
[!NOTE]
Please read the JSDoc I wrote for the client here.
- Creating a client --
-
Then I use it to get a score assessment from Google.
-
And finally I do a quick interpretation of the score and decide whether the action was performed by a human or a bot --
isBot
.
-
Congrats, now you have a fully functional reCAPTCHA implementation in htmx, and your backend does not really mater since their logic is what they should take care of it. But here we used the lovely ExpressJS.
https://dev.to/kasir-barati/implement-recaptcha-in-htmx-expressjs-4k1l