Igor Simic
4 years ago

How to setup invisble reCaptcha using Angular and Laravel


Google reCaptcha V3 is a invisible reCaptcha and it returns a score from 0.0 (most likely a bot) to 1.0 (good interaction) and here is a tutorial how to set it up using Laravel and Angular. 

For this tutorial you will have to have already installed and setup AngularLaravel and Node package manager

Frontend
Let's first setup frontend side on Angular. Here we will use package https://github.com/DethAriel/ng-recaptcha, to install use this npm command. Go to your Angular folder and execute this in terminal:
npm i ng-recaptcha --save
1. import recaptcha module, open app.module.ts and this
import { RECAPTCHA_V3_SITE_KEY, RecaptchaV3Module } from 'ng-recaptcha';

...

@NgModule({
  ...
  imports: [
    RecaptchaV3Module,
    ...
  ],
  providers: [
    { provide: RECAPTCHA_V3_SITE_KEY, useValue: '<YOUR_SITE_KEY>' },
  ],
})
export class MyAppModule { }
To get the Google site key, go to https://www.google.com/recaptcha/intro/v3.html and click on Admin Console, then click on plus sign to create new reCaptcha V3 add your domain. If you are testing on localhost do not forget to add localhost as a domain.
Open your newly created reCaptcha, click on settings button  and then on reCaptcha keys. Use Site Key in Angular app.module.ts and secret key will be used in backend for validation.

2. When your key is set, you can use reCaptcha service in your component
import { ReCaptchaV3Service } from 'ng-recaptcha';
import {Subscription} from 'rxjs';
....
// recaptcha
public recentToken: string = ''
private singleExecutionSubscription: Subscription;

recaptchaAvailable = false;
constructor(
  
  private recaptchaV3Service: ReCaptchaV3Service
) { }

// create function to get the recaptcha key based on event
getRecaptchaToken(action){

    this.singleExecutionSubscription = this.recaptchaV3Service.execute(action)
        .subscribe(response => {
            this.recentToken = response;
            this.recaptchaAvailable = true;
        },error=>{
          console.log("error getting recaptcha");
          this.OnDestroy()

        });
}

// in our case, we will use ngOnInit() function to trigger reCaptcha
ngOnInit() {
   this.getRecaptchaToken('register');
}


// on submit form we can just add  reCaptcha token with submitted data
onSubmit(){
  
  // if we have recaptcha add it to registerForm
  if(this.recaptchaAvailable){
    // do we have recaptcha token?
   this.registerForm.value.rcToken = this.recentToken;
 }
 
 //submit data
 ...
}

Now the reCaptcha token will be submitted to backend, token will be valid for 2 minutes and now we will move to Laravel side.

3. Create Laravel method to validate reCaptcha token:
public function isReCaptchaValid($rcToken){

    $client = new Client([
        'base_uri' => 'https://google.com/recaptcha/api/',
        'timeout' => 5.0
    ]);

    $response = $client->request('POST', 'siteverify', [
        'query' => [
            'secret' => config('app.reCaptchaSecretKey'),
            'response' => $rcToken
        ]
    ]);

    $data = json_decode($response->getBody());

    if($data->success && $data->score >= 0.5){

        return true;

    }

    return false;


}
Google will send back the json object which will look like this:
{
 "success":true,
 "challenge_ts":"2019-08-05T12:33:23Z",
 "hostname":"localhost",
 "score":0.9,
 "action":"register"
}

Here you can see the score which we mentioned before, and as you can see (by the recommendation from  Google) our Laravel method checking is the score 0.5 or higher and in this case it returns true, otherwise it will return false.

If you want, you can extend this method and have different score based on different events. For example, on login you can accept lower score, and on registration higher...

More info about Google reCaptchaV3 you can find on official Google documentation site

And that is it.
See you later Alligator.