Google Token Authentication with node.js and express.js - javascript

I have a node.js/express webservice that I would like to use to verify Google token coming from a mobile app.
From this tutorial (https://developers.google.com/identity/sign-in/android/backend-auth) I learned that I have to make such a call:
https://www.googleapis.com/oauth2/v3/tokeninfo?id_token=XYZ123
So I came up with this in my code:
var request = require('request');
module.exports = function(app) {
app.get('/authenticate', function(req, res) {
request('https://www.googleapis.com/oauth2/v3/tokeninfo?id_token=XYZ123', function (error, response, body) {
if (!error && response.statusCode == 200) {
console.log(body)
}
})
});
};
Then, based on the response from google api, I would like to return true or false.
But it doesn't work. When I put "https://www.google.com" in the request, body is printed in the console, but the request is still being executed for some time.
What am I missing here? Is is the correct approach to the problem I described or should I do it in a completely different way?

You need to send a response to your incoming HTTP request.
Call res.send(...).
For more information, see the Express documentation.

Related

Stop execution after writing to text file with fs.writeFile

I have the following Node.JS (ran with Express) code :
let app = express();
app.use(cors());
app.get('/callback', function (req, res) {
// your application requests refresh and access tokens
// after checking the state parameter
var code = req.query.code || null;
var authOptions = {
url: 'https://accounts.spotify.com/api/token',
form: {
code: code,
redirect_uri: redirectUri,
grant_type: 'authorization_code'
},
headers: {
'Authorization': 'Basic ' + (new Buffer(clientId + ':' + clientSecret).toString('base64'))
},
json: true
};
request.post(authOptions, function (error, response, body) {
if (!error && response.statusCode === 200) {
var access_token = body.access_token,
refresh_token = body.refresh_token;
fs.writeFile('test.txt', 'HELLO', function (err) {
if (err) return console.log(err);
console.log('Hello World > helloworld.txt');
});
}
}
)
});
console.log('Listening on 8888');
app.listen(8888);
The route is used as a callback for a request to the Spotify Web API, thus I can get an access token.
Spotify then redirects to the callback function above, you can see it in the URI by looking at "redirect_uri".
If you need more information about the Spotify Authorization Flow, see here.
Here's the URI I'm using to authenticate my app to Spotify.
https://accounts.spotify.com/authorize?client_id=CLIENT_ID&response_type=code&redirect_uri=http://localhost:8888/callback&scope=user-read-private%20user-read-email%20playlist-modify-public&state=PexBrjEzISHepTp7&show_dialog=false
CLIENT_ID is replaced by my real CLIENT_ID in the request I make
My problem is located to the file writing part :
fs.writeFile('test.txt', 'HELLO', function (err) {
if (err) return console.log(err);
console.log('Hello World > helloworld.txt');
});
When the callback route is called by Spotify, I have the string "HELLO" wrote in my text file, so the file writing is functional.
But even if it has finished writing the string, the Chrome page is still running and "pending" on the server. It runs for a few minutes and then crash by saying that the page didn't sent any data. Why ?
I've looked at this page talking about the methods of writing to text files, using writeFile and writeFileAsync, but using both of them didn't solved my problem.
EDIT: I don't really want to stop the Express process! I just want to be able to process another request :)
Any idea ? Thanks in advance :)
You aren't returning anything from your route, try adding res.send({})
In your get route you are not sending response, you must send response irrespective of writing a file was successful or not.
Add below code post writing to file (as well as in if error case)
res.send({YOUR_CHOICE_RESPONSE_DATA})

How to call web service from Alexa Lambda function

I want to make a GET request to a web site using the Amazon Profile API. I am trying to do what is described in the last code chunk in this article: https://developer.amazon.com/blogs/post/Tx3CX1ETRZZ2NPC/Alexa-Account-Linking-5-Steps-to-Seamlessly-Link-Your-Alexa-Skill-with-Login-wit (very end of article) and it just does not happen. My callback function never seems to get called.
I have added the required context.succeed(), actually the latest version of that, and am still not getting results. I know the url is good, as I can take it and copy/paste into a browser and it returns an expected result.
Here is a SO answer on using the appropriate context function calls within the callback, which I have tried. Why is this HTTP request not working on AWS Lambda?
I am not using a VPC.
What am I doing wrong? I feel like a moron, as I have been researching this and trying solutions for 2 days. I log the full URL, and when I copy/paste that out of the log file, and put it in a browser window, I do get a valid result. Thanks for your help.
Here is the code:
function getUserProfileInfo(token, context) {
console.log("IN getUserProfileInfo");
var request = require('request');
var amznProfileURL = 'https://api.amazon.com/user/profile?access_token=';
amznProfileURL += token;
console.log("calling it");
console.log(amznProfileURL);
console.log("called it");
request(amznProfileURL, function(error, response, body) {
if (!error && response.statusCode == 200) {
var profile = JSON.parse(body);
console.log("IN getUserProfileInfo success");
console.log(profile);
context.callbackWaitsForEmptyEventLoop = false;
callback(null, 'Success message');
} else {
console.log("in getUserProfileInfo fail");
console.log(error);
context.callbackWaitsForEmptyEventLoop = false;
callback('Fail object', 'Failed result');
}
});
console.log("OUT getUserProfileInfo");
}
This is the logging output I get in CloudWatch:
2017-03-08T22:20:53.671Z 7e393297-044d-11e7-9422-39f5f7f812f6 IN getUserProfileInfo
2017-03-08T22:20:53.728Z 7e393297-044d-11e7-9422-39f5f7f812f6 OUT getUserProfileInfo
Problem might be that you are using var request = require('request'); which is external dependency and will require you to make a packaged lambda deployment for it to work. See this answer for relevant information.
AWS Node JS with Request
Another way is that you can use NodeJS module such as var http= require('http'); which is builtin module to make the requests. This way you can just make plain lambda script deployment.
Reference
http://docs.aws.amazon.com/lambda/latest/dg/nodejs-create-deployment-pkg.html

Using request to log into a website?

Hi I am trying to use request module to authenticate myself in http://www.vesseltracker.com/
How do I do that? This is what I did but it won't work
let uu = 'http://*censored*:*censored*#www.vesseltracker.com/';
request(uu, ((err, res, body) => {
console.log(res.statusCode);
}));
Check the documentation from request available here. It looks like you are not making the request properly.
https://www.npmjs.com/package/request#http-authentication

Refresh api query with Node.JS & Heroku

I'm building a messenger bot that queries an API once a day and sends the information contained there to users. it's hosted on Heroku and uses Node.js
I'm currently using this to query the API:
var request = require('request');
//url for classes JSON
var url = 'https://example.api';
//get JSON, parse it and store it in jsonstorage variable
request(url, (error, response, body)=> {
if (!error && response.statusCode === 200) {
jsonstorage = JSON.parse(body)
console.log("Got a response")
} else {
console.log("Got an error: ", error, ", status code: ", response.statusCode)
}
})
The problem with this is that it doesn't refresh the API query ever, so the values returned are always the same. If I try and put it within the functions that send the data once a day though, it claims the jsonstorage variable is 'undefined'.
How can I refresh the query regularly?
Thanks!
Found an answer to this myself - the issue I was running into was that request is asynchronous, so I needed to wait for request to receive a result before running the rest of the script.

Handling asynchronous responses in node on server side

I am trying to build a simple node service that
Handles a GET request from a web client
Parses the params submitted
Uses those params to query another REST service asynchronously
Returns the REST service results back to the original GET request.
I'm just getting started with asynchronous programming in node, in general I'm struggling to understand how to preserve scope between asynchronous calls.
Basically - how do I send the JSON service 'result' back to the original GET request via the 'req'?
I'm using Express and Request, the route handler looks like:
exports.list = function(req, res){
var params = req.query;
var queryParam= params.queryParm;
var restURL = "http://some-json-service.com?queryParam=" + queryParam;
var request = require('request');
request(restURL, function (error, response, body) {
if (!error && response.statusCode == 200) {
var result = JSON.parse(body);
// ? How do I send result back to the req?
}
})
You can literally return the response, so where you have your comment you will do:
request(restURL, function (error, response, body) {
if (!error && response.statusCode == 200) {
var result = JSON.parse(body);
res(result)
}
})
the problem with this approach is that your client request will be pending a response from the second service which is fine if it has to be done. Just be aware of the delay that you might be causing.
Also make sure in case of an error you also return a response.
This seems simple enough, so let me know if I didn't fully understand your question.
Cheers.
Vitor.

Categories

Resources