invalid-input-secret for google's recaptcha api - node.js

I'm trying to use recaptcha on my website. Nodejs server with express framework. The site isn't being hosted, I'm still working on it locally. On the homepage, after the user enters his info to create an account, and solves the recaptcha, I send the results
$("#g-recaptcha-response").val()
to the server. And on my server,
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);
}
});
});
where key is the response and SECRET is the secret key they give you. I declared
a variable SECRET and stored the secret key as a string in it.
Every single time, the for the
console.log(parsedData);
It's saying
{ success: false, 'error-codes': [ 'invalid-input-secret' ] }
I copied and pasted the secret key, how could it be invalid. It's only supposed to show this error if "The secret parameter is invalid or malformed" as it says on their website. I followed this tutorial.

I followed the tutorial too and then bumped into the same error that you have reported here. Looking closely at the screenshot in the tutorial it shows
Send a GET request with these parameters
And checking the Google reCaptcha website it says
Send a POST request with these parameters
I am curious whether Google changed their mind about POST instead of GET or the screenshot in the tutorial is from a different source.
Regardless, I have tweaked the version of code in the tutorial to make POST request (below code uses querystring module), see below:
var SECRET = "YourSecretHere";
// Helper function to make API call to recatpcha and check response
function verifyRecaptcha(key, callback) {
//declare above var querystring = require('querystring') on top
var post_data = querystring.stringify({
'secret' : SECRET,
'response': key
});
var post_options = {
host: 'www.google.com',
port: '443',
method: 'POST',
path: '/recaptcha/api/siteverify',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': Buffer.byteLength(post_data)
}
};
var req = https.request(post_options, 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);
}
});
});
req.write(post_data);
req.end();
req.on('error',function(err) {
console.error(err);
});
}
I also wanted to add that remoteip field is optional but, you can pass that value too if you want too. In order to do that, you need to retrieve the remoteIpAddress from connection object or simply enable trust proxy on your app as shown below:
app.enable('trust proxy');
and then pass the ip address to the verifyRecaptcha and the call would look like follow:
verifyRecaptcha(req.ip, req.body["g-recaptcha-response"], function(success) {
if(success) { ...} else { ... }
});
You then need to modify the post_params to include remoteip field as follow:
var post_data = querystring.stringify({
'secret' : SECRET,
'response': key,
'remoteip': ip
});
app.enable('trust proxy'); allows req.ip and req.ips which is an array of ip addresses. For more info on getting the ip address of request see this SO question.
If you are developing and you get fed up with all tricky famous and the most annoying Street Names reCaptcha, then I recommend that you use the test Site and Secret keys provided by Google to override captcha solving in order to speed up development. See here

This is really stupid, and I can't believe I wasted this much time on it but instead of using the variable SECRET, I just added my secret key to the url and it worked.

Related

Node.js Lambda Function "response is invalid" Amazon Alexa

UPDATE: I had a mistake on my http request endpoint. I had not set the appropriate authentication options so that fixed a lot of errors possibly this specific one.
My question is similar to one here:
Node.js Lambda function returns "The response is invalid" back to Alexa Service Simulator from REST call
However the solution to that question does not solve my problem. So I make an http request call to an xsjs service in Hana cloud. I am getting the 'response is invalid' error message. I can't see why. Here is my function:
// Create a web request and handle the response.
function httpGet(query, callback) {
console.log("/n QUERY: "+ query);
var host = 'datacloudyd070518trial.hanatrial.ondemand.com';
var path = '/LocationInformation/getLocationInfo.xsjs?location=';
var hostname = 'https://' + host + path + query;
var auth = 'user1:D1anafer';
var req = http.request({'hostname': hostname,
'auth': auth
}, (res) => {
var body = '';
res.on('data', (d) => {
body += JSON.stringify(d);
});
res.on('end', function () {
callback(body);
});
});
req.end();
req.on('error', (e) => {
console.error(e);
});
}
And the function that calls it:
'getNewsIntent': function () {
//self = this;
httpGet(location, function (response) {
// Parse the response into a JSON object ready to be formatted.
//var output = JSON.parse(response);
//output = output['change'];
var output = response;
var cardTitle = location;
var cardContent = output;
alexa.emit(':tellWithCard', output, cardTitle, cardContent);
});
},
Thank You
-Diana
Inside your AWS account go to your Lambda function and click on the monitoring tab, where you should see "View Logs in Cloudwatch" in the right hand corner. If you click that link and you should see the errors that are being produced.
You can also use console.log() to log any information being returned from your REST api, which will be logged in cloudwatch and can help you see where your errors are.
This is just a guess from the top of my head. To really help some detailed error message would be required like mentioned about.
But just a guess: Your http.request() is using the http module (https://nodejs.org/api/http.html) and your are accessing the a https resource. If so there is a https (https://nodejs.org/api/https.html) module or use something like axios https://www.npmjs.com/package/axios or requestjs (https://github.com/request/request) this will handle both.
Like I said just a blind guess without detailed error message and seeing your require statements but I am happy to dive deeper if you happen to have details.
HTH
Your callback from the Lambda has to return a valid status code and body. Like this:
let payload = {
statusCode: 400,
body: JSON.stringify('body'),
headers: {"Access-Control-Allow-Origin": "*"}
};
callback(null, payload);
On top of that, to call this from client side code, you have to pass the CORS header back.

Getting Checking your browser before accessing template and 503 status code with https.request(options,callback) node.js

I want to get the html of this page for parsing(click the link to understand what content i want to get).
750-bond list
Here's my code to request this page content
var https = require("https");
var fs = require("fs");
var options = {
hostname: "www.prizebond.net",
port: 443,
path: "/dlist.php?num=455",
method: "GET"
};
var response = "";
var req = https.request(options, function (res) {
res.setEncoding("UTF-8");
console.log(res.statusCode);
res.on("data", function (chunk) {
response += chunk;
});
res.on("end", function () {
fs.writeFile("750-bond.html", response, function (err) {
if (err) {
console.log(err.message);
}
console.log("File downloaded");
});
console.log("end");
});
});
req.end();
Now the problem is that in my 750-bont.html file, I am getting the weird the
result of "Checking your browser before accessing the prizebond.net" not the
original content. Here's the screenshot what I got when I open the 750-
bond.html file in browser.
What I am doing wrong? And how can I get the original content of this webpage?
You can't, unless you write something more sophisticated, but you probably shouldn't.
The purpose of Cloudflare-protection is to prevent what you are trying to realize unfortunately.
You could look into a possibility to access whatever you want to access by a public API or something that prizebond.net provides for example.

Node.js blockchain bitcoin api

So I want to use this: (taken from their API site -> node.js documentation)
https://github.com/blockchain/api-v1-client-node
Recieving payments:
https://github.com/blockchain/api-v1-client-node/blob/master/docs/Receive.md
var blockchain = require('blockchain.info');
var identifier = 'myidentifier';
var password = 'mypassword';
var myWallet = new blockchain.MyWallet(identifier, password);
var myBTCadress = '14Q3ufL1BUHtWskBKtsshVDATRY65TaJMB';
Ok, so the recieving part:
var receive = new blockchain.Receive( [confirmations: 1], ? ); // What do I need to put here?
Documentation says:
callbackURL: the url to which the callback should be sent (string)
I don't understand what URL it should go to?!
The callback URL should be the one that redirects back to your site. So setup a callback url with blockchain like...
https://www.yoursite.com/callback/blockchain
Assuming you are using something like express in your app make a route like so.
app.get('/callback/blockchain', function (req, res) {
// Stuff here
});
you will prob need to include
var https = require('https');
That way then you can set up your logic inside for example...
// Stuff here
var options = {
host : 'api.blockchain.info',
path : '/some/path/',
port : 443,
method : 'GET'
}
var request = https.request(options, function(response){
var body = ""
response.on('data', function(data) {
body += data;
});
response.on('end', function() {
res.send(JSON.parse(body));
});
});
request.on('error', function(e) {
console.log('Problem with request: ' + e.message);
});
request.end();
That will for example output you request in json on whatever page you have your app.get('whateverurl') set to.

Given a recording SID, how can I download the recording file to local drive (using Twilio node helper library)?

I am using the Twilio Node Helper Library to make a call and record it.
According to the API link, GET should return a WAV file, but in my case it just returns a json with the recording metadata.
This is what I'm writing:
twilioClient = require('twilio')(config.twilio.acct_sid, config.twilio.auth_token)
var request = twilioClient.recordings('RE01234567890123456789012345678901')
get(function (err, recording){ // <- this "recording" is JSON
It doesn't matter if I tack on a '.mp3' to the end of the SID, I always get a JSON.
Ideally I want to write something like this:
var file = fs.createWriteStream('/Users/yasemin/Desktop/rec.mp3');
twilioClient.recordings('RE01234567890123456789012345678901')
.get(function (err, recording) {
if(!err){ recording.pipe(file); }});
Thanks!
I came across this and had to develop my own code to handle this.
Here is the code I came up with below
con.on('getvmx', function(data){
comModel.find({_id: data.id}, function(err, results){
var https = require('https');
var options = {
host: 'api.twilio.com',
port: 443,
path: '/2010-04-01/Accounts/' + sid + '/Recordings/'+ results[0].sid + '.mp3',
method: 'GET',
auth: sid + ":" + auth,
agent: false
};
var req = https.request(options, function(res) {
res.setEncoding('binary');
var mp3data = '';
res.on('data', function (chunk) {
mp3data += chunk;
});
res.on('end', function(){
try{
var fileName = "/var/www/tcc/public/vm/" + results[0].sid + '.mp3';
fs.writeFile(fileName, mp3data, 'binary', function(err){
if(err){
return console.log(err);
}else{
console.log("File Saved");
con.emit('vmload', results);
}
});
}catch(err){
console.log(err.message);
}
});
});
req.end();
console.log(results);
//load all messages
//load line from reach message
});
});
TLDR: Node Helper Library doesn't have recoded file downloading capability at the moment.
This is the response from Twilio Support:
Looking at the documentation on our web portal, you are certainly
correct, downloading the .wav or .mp3 is possible via API call.
However, from what I can see looking at the Node example code here:
https://www.twilio.com/user/account/developer-tools/api-explorer/recording
And the documentation from the Twilio-Node developer here:
http://twilio.github.io/twilio-node/#recordings
It looks to me like the helper library doesn't actually support direct
downloading, just viewing the recording data. You can download the
application through an HTTP call, as shown in the original docs link
you noted on your Stackoverflow question. Let me know if you need help
with that.
In the mean time, I've reached out to the author of the library to see
if this is by design or a feature to be added to the library. It's
open source of course, so you could make a pull and add it yourself if
you like!

ExpressJS - contact external API

Here is the thing :
I have a client which sends data to a server. This server has to contact an external A.P.I. and send back its response to the client. I just can't figure out how and where I can contact the external A.P.I once the server has got the client data.
I route client data like this :
app.post('/getAutoComplete', routes.read);
routes.read retrieves the data within req.body. With my nodejs version (without express framework), I then request the api this way :
var http = require('http'), options = {
host : "192.168.1.38",
port : 8080,
path : "/myURL",
method : 'POST'
};
var webservice_data = "";
var webservice_request = http.request(options, function(webservice_response)
{
webservice_response.on('error', function(e){ console.log(e.message); });
webservice_response.on('data', function(chunk){ webservice_data += chunk;});
webservice_response.on('end', function(){res.send(webservice_data);});
});
webservice_request.write(req.body);
webservice_request.end();
The problem is that i'd like to use native expressJS method like app.post but I don't know how because :
Express (app) object is not available here (declared in app.js but not in the route file)
I don't know how to send POST data with app.post
Any suggestion ?
app.post('/getAutoComplete', routes.read);
// assuming routes.read lookes something like this
routes.read = function read(req, res) {
var http = require('http'), options = {
host : "192.168.1.38",
port : 8080,
path : "/myURL",
method : 'POST'
};
var webservice_data = "";
var webservice_request = http.request(options, function(webservice_response)
{
webservice_response.on('error', function(e){ console.log(e.message); });
webservice_response.on('data', function(chunk){ webservice_data += chunk;});
webservice_response.on('end', function(){res.send(webservice_data);});
});
webservice_request.write(req.body);
webservice_request.end();
};
Also check out https://github.com/mikeal/request It's the de-facto module for doing web requests in node.
routes.read is a function. You can call it with extra parameters, so for example
app.post('/getAutoComplete', function(req,res) {
var q = req.query.q; // or whatever data you need
routes.read(q, function(err, response) {
if (err) throw err;
return res.json(response);
});
});
Now make the routes.read function use the first parameter as the query and when it's gathered the response from the remote API, call the second parameter with any error as the first parameter and the response as the second one.
Update This answer has already been picked as an answer, but it'd be more helpful if I showed an example of routes.read, too:
routes.read = function(q, cb) {
// pretend we calculate the result
var result = q * 10;
if (result > 100) {
// call the callback with error set
return cb("q value too high");
}
// all is well, use setTimeout to demonstrate
// an asynchronous return
setTimeout(function() { cb(null, result) }, 2000);
};

Resources