Using the new noCAPTCHA reCAPTCHA with Node.js and Express

Using the new noCAPTCHA reCAPTCHA with Node.js and Express

 

Google recently released a new version of reCAPTCHA that eliminates typing for many users. Here's a quick how-to for integrating it in your Node.js application.

We're going to use Express for simplicity, but these steps are mostly agnostic and could be wrapped into any application.


Step 1: Register your site

Head over to the reCAPTCHA site and add your website to the list. You'll be presented with a screen like this:


Copy down the secret and site keys, you'll need them soon.

Step 2: Integrate it

 

Build out a basic Node.js application. The key point is that your HTML view will contain the div listed on the reCAPTCHA settings page, along with the reCAPTCHA client-side JavaScript. On the server, a function similar to the following is needed to verify the submitted claim with the reCAPTCHA server:

function verifyRecaptcha(key, callback) {
    https.get("https://www.google.com/recaptcha/api/siteverify?secret=" + SECRET + "&response=" + key, function(res) {
        var data = "";
        res.on('data', function (chunk) {
                        data += chunk.toString();
        });
        res.on('end', function() {
            try {
                var parsedData = JSON.parse(data);
                console.log(parsedData);
                callback(parsedData.success);
            } catch (e) {
                callback(false);
            }
        });
    });
}

 

Here's an example:

<!doctype html>

<html>

<head>

<script src='https://www.google.com/recaptcha/api.js'></script>

</head>

<body>

<h1>Register for test site</h1>


<form action="register" method="post">

<input type="text" name="username" placeholder="Username"><br>

<input type="text" name="email" placeholder="Email"><br>

<input type="password" name="password" placeholder="Password"><br>

<div class="g-recaptcha" data-sitekey="sitekey here"></div>

<input type="submit" value="Register">

</form>


</body>

</html>

form.html 

var express = require('express');

var bodyParser = require('body-parser');

var engines = require('consolidate');

var app = express();


var https = require('https');


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

app.engine('html', engines.hogan);


app.get('/', function(req, res) {

res.render('form.html');

});


app.post('/register', function(req, res) {

verifyRecaptcha(req.body["g-recaptcha-response"], function(success) {

if (success) {

res.end("Success!");

// TODO: do registration using params in req.body

} else {

res.end("Captcha failed, sorry.");

// TODO: take them back to the previous page

// and for the love of everyone, restore their inputs

}

});

});


app.listen(3000);


var SECRET = "secret from webpage here";


// Helper function to make API call to recatpcha and check response

function verifyRecaptcha(key, callback) {

https.get("https://www.google.com/recaptcha/api/siteverify?secret=" + SECRET + "&response=" + key, function(res) {

var data = "";

res.on('data', function (chunk) {

data += chunk.toString();

});

res.on('end', function() {

try {

var parsedData = JSON.parse(data);

callback(parsedData.success);

} catch (e) {

callback(false);

}

});

});

}
index.js

 


{

"name": "nodejs-recaptcha",

"version": "1.0.0",

"description": "",

"main": "index.js",

"scripts": {

"test": "echo \"Error: no test specified\" && exit 1"

},

"author": "",

"license": "ISC",

"dependencies": {

"consolidate": "^0.10.0",

"express": "^4.10.4",

"hogan.js": "^3.0.2"

}

}


In this case, we're using a normal form submit to carry over the CAPTCHA data and perform the registration. More and more web applications are becoming single-page JavaScript applications, though, so using an AJAX API to perform registration would be preferred. Here's a quick and dirty example of how you
would handle that scenario:


<!doctype html>

<html>

<head>

<script src='https://www.google.com/recaptcha/api.js'></script>

<script>

function registerAPI(form) {

var params = {

username: form.username.value,

password: form.password.value,

email: form.email.value,

recaptcha: document.getElementById("g-recaptcha-response").value

};



var xhr = new XMLHttpRequest();

xhr.open("POST", "/register");

xhr.onload = function() {

var json = JSON.parse(xhr.responseText);

console.log(json);

if (json.registeredSuccessfully) {

showSuccess();

} else {

showError(json.reason);

}

}

xhr.setRequestHeader("Content-type", "application/json");

xhr.send(JSON.stringify(params));

}



function showSuccess() {

document.getElementById("form").style.display = "none";

document.getElementById("success").style.display = "block";

}



function showError(err) {

document.getElementById("error").innerHTML = err;

}

</script>

</head>

<body>

<h1>Register for test site</h1>


<form action="register" method="post" onsubmit="registerAPI(this);return false;" id="form">

<span id="error"></span><br>

<input type="text" name="username" placeholder="Username"><br>

<input type="text" name="email" placeholder="Email"><br>

<input type="password" name="password" placeholder="Password"><br>

<div class="g-recaptcha" data-sitekey="sitekey here"></div>

<input type="submit" value="Register">

</form>


<div id="success" style="display:none">

Successfully registered, yay.

</div>


</body>

</html>
form.html 




var express = require('express');

var bodyParser = require('body-parser');

var engines = require('consolidate');

var app = express();


var https = require('https');


app.use(bodyParser.json());

app.engine('html', engines.hogan);


app.get('/', function(req, res) {

res.render('form.html');

});


app.post('/register', function(req, res) {

verifyRecaptcha(req.body["recaptcha"], function(success) {

if (success) {

res.end(JSON.stringify({ registeredSuccessfully: true }));

// TODO: do registration using params in req.body

} else {

res.end(JSON.stringify({ registeredSuccessfully: false, reason: "Captcha failed, try again." }));

// TODO: take them back to the previous page

// and for the love of everyone, restore their inputs

}

});

});


app.listen(3000);


var SECRET = "secret from webpage here";


// Helper function to make API call to recatpcha and check response

function verifyRecaptcha(key, callback) {

https.get("https://www.google.com/recaptcha/api/siteverify?secret=" + SECRET + "&response=" + key, function(res) {

var data = "";

res.on('data', function (chunk) {

data += chunk.toString();

});

res.on('end', function() {

try {

var parsedData = JSON.parse(data);

console.log(parsedData);

callback(parsedData.success);

} catch (e) {

callback(false);

}

});

});

}
index.js 



{

"name": "nodejs-recaptcha",

"version": "1.0.0",

"description": "",

"main": "index.js",

"scripts": {

"test": "echo \"Error: no test specified\" && exit 1"

},

"author": "",

"license": "ISC",

"dependencies": {

"consolidate": "^0.10.0",

"express": "^4.10.4",

"hogan.js": "^3.0.2"

}

}
package.json


All in all, it's pretty simple, and worked well in my tests. I'll be sure to integrate this into some of my upcoming projects, now that both integrating and solving CAPTCHAs has become very easy.

If you have any questions or concerns about it, feel free to drop a note in the comments.

Comments

Popular posts from this blog

Private Chat Using Node js and socket.io with encrypt and decrypt message and insert into mongo db

How To Migrate MVC 3 Application To MVC 5

Populate a drop-down in Vue.js and Asp.net Core from an ajax call