Skip to main content

ReCaptcha v2 in Angular 8 with Back-end verification with Nodejs

Angular is powerful and modern framework for secured and standard that provides almost every basic developers needs in one package, from form validators, Rxjs library, PWA integration and lots more. However, it also gives room fr integrating other API such as Recaptcha (the main concern of this article). Hence, i will be putting you through on how to integrate reCaptcha to angular (v8) and how to validate at backend with nodejs.

ReCAPTCHA is a free service that protects your website from spam and abuse, and it is always useful in registration forms and others. Alright lets hit the road.

Setting up Angular project

if done with the process above your angular file should be up and running.

next up install the reCaptcha library using npm in CMD. inside your angular project folder run the command

npm install ng-recaptcha --save

this should install the reCaptcha API into your angular project.

Configuring the reCaptcha library for you project.

<base href=”/”> include the script below

<script src="https://www.google.com/recaptcha/api.js" async defer></script>

Next up, go to the google recaptcha siteto create a SITE KEY (for front end Angular) and a SECRET KEY (for backend verification with node). while in the site, click on admin console at the top right corner, then in the admin console click on the plus-like icon to register a new site. fill the form as below;

notice that the domain list contains localhost. this is for development purpose. when done click on the Submit button to create

Next, click the settings-like icon to get your site key for your angular part

your site key and secret key should look like

copy the site key.

Including the Site key and rendering the reCaptcha interface

import { RecaptchaModule, RecaptchaFormsModule } from 'ng-recaptcha';

@NgModule({
  declarations: [
    AppComponent,
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
    HttpClientModule,
    ReactiveFormsModule,
    FormsModule,
    BrowserAnimationsModule,

    RecaptchaModule,  //this is the recaptcha main module
    RecaptchaFormsModule, //this is the module for form incase form validation
  ],
  entryComponents:[],
  providers: [ ],
  bootstrap: [AppComponent]
})
export class AppModule {}



Remember we included the reCaptcha script before in our app/src/index.html file to render the reCaptcha interface.

Lets assume we are using the app/src/app.component.html file. to show the reCaptcha interface include the code in any *.component.html file you want to use it. in my case i am using the app.component.html file


<div>
  <!-- 
    the SITE_KEY is the sitekey from your admin console.
    use form control for validation
  -->
  <re-captcha (resolved)="resolved($event)" 
              formControlName="recaptchaReactive" 
              siteKey="SITE_KEY">  
  </re-captcha>
</div>

Bravo! we are almost there. Now check if your reCaptcha interface shows. load the page after ng serve

if it shows, you are configured correctly.

Resolving the I-am-not-a-robot interface and retrieving a token for backend validation

before resolving, notice the app-recaptcha we included to render our recaptcha interface

<re-captcha (resolved)="resolved($event) sitekey="SITE_KEY"></re-captcha>

notice the event

(resolved)=”resolved($event)”

this is the event that binds to the resolved function in the component.ts file . hence, to complete it, we need to include the resolved($event) function in app.component.ts.

resolved(captchaResponse: string, res) {  console.log(`Resolved response token: ${captchaResponse}`);

}

with this, when the reCaptcha is checkbox is clicked and checked, the resolved function gets called and the response is a token. the response will lok like this

Resolved response token: 03AsdsdfsSxBIiZC-cYcch6y-BaWrmfB9iOvvU3UiT9J4zF-WxQ9p74dmIFUJOoZ6dg6U-7vW1H_Ds29hI5oRoY10_Yr_FaVe6mW52uaxIPgkIcZv13Mx3ssTX5Hg6leBC3ihfuKUSsg3lDfxbaTmONfshidbHs_yMRtiPYnv79ZWm75cpwXDcpY1RaI5SWZMf5yXnCkmGDwmV9Mo2yqnYuwA70g8Ouf8cdzfsdfsdfcWIVFJSYS6KN2GjL0TudbMxpOxdyEHEVb5KKkTjVe8rWYHwkg9755rgaRi5csTVRATD4zH36JmMAXTuXBNS_LaQHsfDjI7m-eeVRYUr72wXs6g9vvGgkBHmw0dGeK6kOreDwAug2baHZXPH8pD5Gu6-hIz7mESBO-qn0XihfYQhBMMdIwTzhvkyerXfvTBCctFGvcTb777qOW16ZWwVGzGXpMWjEm_DdHSnjwjROwZdog8jsdbfUghaihsgiuWn9VZAb2-NnVkV6c61NUlR-C6m12_3UGHZt4uVtxeTMjhqHdix-SQTh_lQ

If this is attained then congratulation you have finally resolved the reCaptcha. however, to complete the circle, we have to validate the token received at the backend with our recaptcha site secret key.

for this case we will use nodejs.

Setting up Nodejs Express backend and Validating token

mkdir app-backend
cd app-backend

After words initialize your app with

npm init

the command will require for certain things from you like description. for (endpoint): index.js, you can us app.js or anything

up next install the express and other necessary dependencies in app-backend folder created earlier

npm install express request body-parser --save

the above command should install express server, request module for making http request to other endpoint and body-parser module for parsing json.

Validating the token

Proxy the node back end

{"/": {"target": "http://localhost:3000/","secure": false}}

the file will point to the node server running on port 3000 (we have not start the server yet).

Next configure your package.json file to use the proxy.conf.json file for proxying. include

--proxy-config proxy.conf.json

in your package.json file as below

"name": "recaptchaApp","version": "0.0.0","scripts": {"ng": "ng","start": "ng serve   --proxy-config proxy.conf.json","build": "ng build","test": "ng test","lint": "ng lint","e2e": "ng e2e"

save and close file. stop the running angular project and re-run the project with

npm start

this should run your project, and proxy to your node backend.

Send token to backend

ng generate service app

this will generate an app.service.ts file in app/src folder

include the HttpClientModule in your app.module.ts to use the HttpClient API

if done, create a simple post request in your service to an end point: token_validate. below is a app.service.ts file (angular service to send the token) and app.component.ts file to use the service to send the resolved token


import { AppService} from "./app.service";

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent{
  
constructor(private service: AppService){
}

//function to resolve the reCaptcha and retrieve a token
async resolved(captchaResponse: string, res) {
  console.log(`Resolved response token: ${captchaResponse}`);
  await sendTokenToBackend(capchaResponse); //declaring the token send function with a token parameter
}

//function to send the token to the node server
sendTokenToBackend(tok){
  //calling the service and passing the token to the service
  this.service.sendToken(tok).subscribe(
    data => {
      console.log(data)
    },
    err => {
      console.log(err)
    },
    () => {}
  );
}



}




import { Injectable } from '@angular/core';
import {HttpClient } from '@angular/common/http'
import { Observable } from 'rxjs';

@Injectable({
  providedIn: 'root'
})
export class AppService {

  constructor(
    private http: HttpClient
  ) { }

 sendToken(token){
    return this.http.post<any>("/token_validate", {recaptcha: token})
  }
    
  
  }

Receiving and validating the token with node server

const express = require('express')
const bodyParser = require("body-parser");
const request = require("request");
const app = express();
const port = 3000;

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));

app.post('/token_validate', (req, res)=>{
      
  let token = req.body.recaptcha;
  const secretkey = "SECRET_KEY"; //the secret key from your google admin console;
  
  //token validation url is URL: https://www.google.com/recaptcha/api/siteverify 
  // METHOD used is: POST
  
  const url =  `https://www.google.com/recaptcha/api/siteverify?secret=${secretKey}&response=${token}&remoteip=${req.connection.remoteAddress}`
   
  //note that remoteip is the users ip address and it is optional
  // in node req.connection.remoteAddress gives the users ip address
  
  if(token === null || token === undefined){
    res.status(201).send({success: false, message: "Token is empty or invalid"})
    return console.log("token empty");
  }
  
  request(url, function(err, response, body){
    //the body is the data that contains success message
    body = JSON.parse(body);
    
    //check if the validation failed
    if(body.success !== undefined && !data.success){
         res.send({success: false, 'message': "recaptcha failed"});
         return console.log("failed")
     }
    
    //if passed response success message to client
     res.send({"success": true, 'message': "recaptcha passed"});
    
  })

})


app.listen(port, ()=>{
    console.log(`connected on port ${port}`)
})


If all is good, run the node server. navigate into the node backend (app-backend) folder using CMD and use the command

node index

this will kick-off your node server. note, the index implies that index.js is your end point. if app.js or server.js use node app or node server.








Comments

Popular posts from this blog

How to use Ngx-Charts in Angular ?

Charts helps us to visualize large amount of data in an easy to understand and interactive way. This helps businesses to grow more by taking important decisions from the data. For example, e-commerce can have charts or reports for product sales, with various categories like product type, year, etc. In angular, we have various charting libraries to create charts.  Ngx-charts  is one of them. Check out the list of  best angular chart libraries .  In this article, we will see data visualization with ngx-charts and how to use ngx-charts in angular application ? We will see, How to install ngx-charts in angular ? Create a vertical bar chart Create a pie chart, advanced pie chart and pie chart grid Introduction ngx-charts  is an open-source and declarative charting framework for angular2+. It is maintained by  Swimlane . It is using Angular to render and animate the SVG elements with all of its binding and speed goodness and uses d3 for the excellent math functio...

Understand Angular’s forRoot and forChild

  forRoot   /   forChild   is a pattern for singleton services that most of us know from routing. Routing is actually the main use case for it and as it is not commonly used outside of it, I wouldn’t be surprised if most Angular developers haven’t given it a second thought. However, as the official Angular documentation puts it: “Understanding how  forRoot()  works to make sure a service is a singleton will inform your development at a deeper level.” So let’s go. Providers & Injectors Angular comes with a dependency injection (DI) mechanism. When a component depends on a service, you don’t manually create an instance of the service. You  inject  the service and the dependency injection system takes care of providing an instance. import { Component, OnInit } from '@angular/core'; import { TestService } from 'src/app/services/test.service'; @Component({ selector: 'app-test', templateUrl: './test.component.html', styleUrls: ['./test.compon...

How to solve Puppeteer TimeoutError: Navigation timeout of 30000 ms exceeded

During the automation of multiple tasks on my job and personal projects, i decided to move on  Puppeteer  instead of the old school PhantomJS. One of the most usual problems with pages that contain a lot of content, because of the ads, images etc. is the load time, an exception is thrown (specifically the TimeoutError) after a page takes more than 30000ms (30 seconds) to load totally. To solve this problem, you will have 2 options, either to increase this timeout in the configuration or remove it at all. Personally, i prefer to remove the limit as i know that the pages that i work with will end up loading someday. In this article, i'll explain you briefly 2 ways to bypass this limitation. A. Globally on the tab The option that i prefer, as i browse multiple pages in the same tab, is to remove the timeout limit on the tab that i use to browse. For example, to remove the limit you should add: await page . setDefaultNavigationTimeout ( 0 ) ;  COPY SNIPPET The setDefaultNav...