Google ReCAPTCHA to AngularJS

Why?

To block robots.

Other captchas?

JavaLite – captcha http://javalite.io/captcha
But I wanted not to challenge any images to users. Google ReCAPTCHA v3 only reads users’ mouse and keyboard interactions and challenge nothing to find out robots.

Is it free?

Yes, commercially free. But Google will collect all users’ interactions all over the website, right on the document.window! If you block this, ReCAPTCHA will not work. (I’ve tested a lot)
I personally think why Google provides this captcha service free is that Google wants to improve AdSense quality using ReCAPTCHA’s data. You know there are a lot of abuses of AdSense and it is a direct threat to Google’s revenue.
And you know there is no destroy() function on it. Once it is on, you cannot remove it. It keeps tracking users’ experience until they go out that page. If you made your website as one unified page, you cannot remove it until refreshing(F5) or logging out. (I’ve also tested a lot)

Sign up & get API keys

https://developers.google.com/recaptcha/
Site key: something (will share with users)
Secret key: something (never share with users)

Add to the client side

import { Directive, OnInit } from '@angular/core';
@Directive({
selector: '[myRecaptcha]'
})
export class MyRecaptchaDirective implements OnInit {
ngOnInit() {
const script = document.createElement('script');
script.src = 'https://www.google.com/recaptcha/api.js?render=' + environment.recaptchaSitekey;
document.body.appendChild(script);
}
}

<div myRecaptcha></div>

import { ... NgZone } from '@angular/core';
declare const grecaptcha: any;
declare global {
interface Window {
buySomething: any;
}
}
constructor(

private ngZone: NgZone
) {

}
ngOnInit() {
window.buySomething = window.buySomething || {};
window.buySomething.namespace = window.buySomething.namespace || {};
window.buySomething.namespace.callbackBuySomething = this.callbackBuySomething.bind(this);
}
clickBuySomething() {
grecaptcha.execute(environment.recaptchaSitekey, {action: 'buy_something'}).then(function(token: string) {
// console.log('grecaptcha.execute() token=' + token);
window.buySomething.namespace.callbackBuySomething(token);
});
}
callbackBuySomething(token: string) {
this.ngZone.run(() => this.saveSomething(token));
}
saveSomething(token: string) {
//call API with token
//then API will throw it is valid or not
}

Add to the server side

@Data
public class GoogleRecaptchaResponse {
Boolean success;
Double score;
String action;
LocalDateTime challenge_ts;
String hostname;
@JsonProperty("error-codes") String[] errorCodes;
}


url: https://www.google.com/recaptcha/api/siteverify
secretKey: something
scoreThreshold: 0.5 #1.0 is very likely a good interaction, 0.0 is very likely a bot

public boolean verifyRecaptcha(String token, String action) {
GoogleRecaptchaResponse gResponse = restTemplate.postForEntity(
URI.create(String.format(url+"?secret=%s&response=%s",secret,token)),
null,
GoogleRecaptchaResponse.class).getBody();
if(gResponse!=null &&
gResponse.getSuccess() &&
gResponse.getScore() > scoreThreshold
&& gResponse.getAction().equals(action)) {
log.info("ReCAPTCHA verification succeeded: {}",gResponse);
return true;
}else {
log.error("ReCAPTCHA verification failed: {}",gResponse);
return false;
}
}

How to test

Postman (just call API) https://www.getpostman.com/
JMeter (record & play) https://jmeter.apache.org/
Selenium WebDriver (build a macro & run) https://www.seleniumhq.org/
…any other suggestions?

References

https://netbasal.com/how-to-integrate-recaptcha-in-your-angular-forms-400c43344d5c
https://stackoverflow.com/questions/35296704/angular2-how-to-call-component-function-from-outside-the-app

Leave a comment

Your email address will not be published. Required fields are marked *