how to parse" http GET request"'s text response in nodejs? - node.js

I make a HTTP GET request to Facebook to have a long live token , as a response I have a plain text with the access token and expiration date , but I don't know how to parse it.
request.get('https://graph.facebook.com/oauth/access_token?client_id=' + APP_ID + '&client_secret=' + APP_SECRET + '&grant_type=fb_exchange_token&fb_exchange_token=' + CURRENT_ACCESS_TOKEN)
.on('data', function(data) {
console.log("body= " + data);
});
res.render('SocialMedia.ejs');
I tried data.access_token but it's undefined

Go through this documentation to get working with the lates 2.8 API (recommended). This will return a JSON response.
If you want to continue using your API then to parse your response which is in the form of url query params -
access_token=(the token)&expires=5166486 // data
You can do this -
var qs = require('qs');
var response = qs.parse(data); // assuming data is as mentioned above
console.log(response); // will print {access_token: (the token), expires: 5166486}
Now you can access the token like this -
response.access_token;

Related

How to retrieve parameters from response body

I am trying to set up Spotify authorization using Authorization Code Flow ( as from https://developer.spotify.com/documentation/general/guides/authorization-guide/#authorization-code-flow ) and got stuck receiving the tokens from the Spotify server.
When I make the POST request, I log the response body and set two variables: access and refresh tokens. The response body indeed contains these tokens, the variables are, however, are undefined (see logs).
console.log("Response.body: ")
console.log(response.body);
var access_token = response.body['access_token'],
refresh_token = response.body['refresh_token'];
console.log("Access: " + access_token);
console.log("Refresh: " + refresh_token);
I've tried both body.access_token and response.body.access_token as well.
A 2019-09-03T09:13:03.184411Z Response.body:
A 2019-09-03T09:13:03.184575Z {"scope":"playlist-modify-private","access_token":"BQAjB5eurOdl3oM2j-8db4pKi-...","token_type":"Bearer","refresh_token":"AQDtEcfw…
A 2019-09-03T09:13:03.184607Z Access: undefined
A 2019-09-03T09:13:03.184618Z Refresh: undefined
Make sure to convert the body to a proper object before trying to access properties.
Try the following:
const body = JSON.parse(response.body);

Creating Stripe Express Connect Account, Getting 'unsupported_content_type' when POST to endpoint for account ID

Im having trouble sending "POST" request to stripes token endpoint at the end of creating connect express account. Currently, my application(ios) is opening the OAuth Link (which contains a redirect uri to my server(Firebase functions)) to the express account creation web page made by stripe. Once the user completes their account set up I receive the authorization code in the backend and then use the authorization code and client_secret_key to send a POST request to "https://connect.stripe.com/oauth/token". I'm using XMLHttpRequest npm to send a POST request within firebase functions and setting my parameters like this
var params = "client_secret=" + CLIENT_SECRET + "&code=" + AUTHORIZATION_CODE + "&grant_type=authorization_code"
and my request header like this
request.setRequestHeader("Content-type", "application/x-www-form-urlencoded")
Yet I get back this error after sending POST request
"error": {
"type": "invalid_request_error",
"code": "unsupported_content_type",
"message": "Invalid request: unsupported Content-Type text/plain;charset=UTF-8. If error persists and you need assistance, please contact support#stripe.com."
}
I thought I was properly setting request header content-type to "application/x-www-form-urlencoded" but still getting back error as if the content-type was "Text/plain".
Here is full backend code
exports.CreateUsersPayoutAccount = functions.https.onRequest((req, res) =>{
const userID = req.query.state
const AUTHORIZATION_CODE = req.query.code
console.log(userID)
console.log(AUTHORIZATION_CODE)
//console.log(req);
var request = new XMLHttpRequest()
request.addEventListener('load', getStripeConnectUserID)
var params = "client_secret=" + CLIENT_SECRET + "&code=" + AUTHORIZATION_CODE + "&grant_type=authorization_code"
//var params = JSON.stringify({client_secret : CLIENT_SECRET, code : AUTHORIZATION_CODE, grant_type : "authorization_code"})
console.log(params);
request.open("POST", "https://connect.stripe.com/oauth/token", true)
request.setRequestHeader("Content-type", "application/x-www-form-urlencoded")
//request.setRequestHeader("Content-length", params.length)
request.send(params)
})
If anyone could point me in the right direction it would be much appreciated, I am somewhat new to writing backend HTTP calls.
In the backend cloud function, rather than attempt to send the POST request from there, write the auth code to a spot in firebase database.
Back in Xcode have a listener function that executes if there's a change in that database spot. The function should then read the change (the auth code) and simply send an easy swifty POST request with Alamofire.
I understand why you made the uri direct to your specific cloud function (since its an http trigger), but isn't the point of sending a uri so that stripe can redirect the user back to a specific app page, does the user still get directed back to the app in your case???

Node JS / Angular 2 application , ForbiddenError: invalid csrf token

I am working on sample application using Node.js for server side and Angular 2 for front end.
To prevent CSRF attacks , I have used "csurf" middleware
Below is the relevant code to set the middleware
// cookie parser
app.use(cookieParser());
// express session middleware , this should be after cookie parser
app.use(session({secret:'clickclick'}));
app.use(session({
secret: 'clickclick',
cookie: {
path:'/',
httpOnly:true,
maxAge:null
}
}));
// CSRF middleware
app.use(csurf());
Below node.js route sets "_csrf" header
router.get('/:id/products/:pid' , wrap(function *(req , res , next) {
try
{
console.log('url' , req.url);
res.setHeader('_csrf', req.csrfToken());
let product = yield category.getProduct(req , res , next);
res.send(product);
}
catch(err)
{
res.status(500).send(err);
}
}))
The above mentioned route '/:id/products/:pid' is called from my below Angular 2 service method
// Get Product
GetProduct(id:string, pid:string):Observable<Product> {
return this.http.get('./categories/' + id + '/products/' + pid)
.map(data =>{ let headers:Headers = data.headers;
this.csrfToken = headers.get('_csrf') ;
return data.json() })
.catch(this.handleError);
}
This method assigns the _csrf header returned from server to "this.csrfToken" property.
And when the below service method makes an AJAX POST request , it uses the "this.csrfToken" property value set by above method and sets header "_csrf" value.
// Add an item to cart
AddTocart(product:Product)
{
let item = { pid:product._id , name:product.name , price:product.price , qty:1 , total:product.price };
//this.cart.push(item);
// make an AJAX call to save the item in server session
let url = './cart/add';
let headers = new Headers({'Content-Type':'application/json' , '_csrf':this.csrfToken});
let requestOptions = new RequestOptions({headers:headers});
this.http.post(url , item , requestOptions)
.map(data => {
this.cart.push(item);
}
)
.catch(this.handleError)
.subscribe( data => { });
}
Below is the Response Header of GetProduct service method.
And below is the request Header of "AddTocart" service method.
Any idea what is causing "ForbiddenError: invalid csrf token" error.
Please let me know if I need to provide more information or if the information provided is not clear.
I know this is an older question, but I'm adding this here in case someone stumbles across it in the future. Working on a similar project and encountered the same error, I fixed it by adding a XSRF-TOKEN header in the POST request, with the value taken from $.cookie("XSRF-TOKEN") (using jquery and the cookies plugin). According to the docs, _csrf should also work though.
From the project page :
The default value is a function that reads the token from the following locations, in order:
req.body._csrf - typically generated by the body-parser module.
req.query._csrf - a built-in from Express.js to read from the URL query string.
req.headers['csrf-token'] - the CSRF-Token HTTP request header.
req.headers['xsrf-token'] - the XSRF-Token HTTP request header.
req.headers['x-csrf-token'] - the X-CSRF-Token HTTP request header.
req.headers['x-xsrf-token'] - the X-XSRF-Token HTTP request header.
As far as I can tell, the error seems to come from POST / PUT requests including the correct cookies, but nodejs / csurf isn't looking for them there.
In your specific case, _csrf should be in the request body along with the cart items, or the header should be renamed to csrf-token, or one of the other options.

Node.js HTTP GET request content type

I am trying to do a GET request from node.js. This request is to a REST server which will access Hbase and return the data. The GET request contains all necessary Hbase info (table, key, column-family etc.) in it. Following is the code.
var http = require('http');
var url = {
host: '127.0.0.1',
port: 8000,
path: '/table-name/key/column-family',
headers: {
'Content-Type': 'application/octet-stream'
},
};
http.get(url, function(resp){
console.log("Status: " + resp.statusCode);
console.log("Header: " + JSON.stringify(resp.headers));
resp.setEncoding('utf8');
var completeResponse = '';
resp.on('data', function (chunk) {
completeResponse += chunk;
});
resp.on('end', function(chunk) {
console.log(completeResponse);
});
});
My problem is that the response I get is not always an octet-stream as requested. Most of the time data is in valid format with a header like the following.
{"content-length":"454","x-timestamp":"1395469504346","content-type":"application/octet-stream"}
But, say 1 out of 10 times the response is an XML string with a header like following.
{"content-type":"text/xml","content-length":"793"}
The status code is 200 in both cases and I am always requesting for an existing key. This behavior is seemingly random and not caused by any particular key.
How do I ensure that the response is always an octet-stream and not XML / JSON?
As stated in the comments, you need to set the Accept header to specify the content type you expect (accept) in response from the server. Note that you may accept more than one type of response.
The Content-Type header specify the type of what's in the body of the message. It can be set by your client in case of POST/PATCH request, or by the server in its response. On the receiving side, it is used to know how to handle the body content.
For more detail, you can refer to the comprehensive MDN content negotiation documentation

Facebook access token not accepted to Open Graph using Node.js facebook-node-sdk

Posting an Open Graph action using the Node.js facebook-node-sdk module gives me {"error": "An active access token must be used to query information about the current user."}.
var FB = require( 'fb' )
var path = '/me?' + namespace + ':' + action_type_name
var body = {
access_token: myAccessToken,
myAction : myCustomObjectURL
}
FB.api( path, 'post', body, function( res )
{
if( res.error ) {
console.log( 'the call to open graph failed: ' + res.error.message );
}
else {
console.log( 'success' )
}
})
If I print this access token and use it with cURL (curl https://graph.facebook.com/me?access_token=myAccessToken), it returns correctly, no error. Facebook also shows that the app has permission to post as this user. So what am I doing wrong here?
D'oh, stupid question. It turns out I needed a slash instead of a question mark in the URL path: path = '/me/' + ...
Actually this is a bug of the node facebook api.
When you use a '?' in your api-calls the accesstoken gets appended with another '?'
https://github.com/Thuzi/facebook-node-sdk/blob/master/fb.js#L268
This leads to a api-call like this one: https://graph.facebook.com/me/friends?limit=10?access_token=vSAEFfionhaWFwai...
You see multible '?' in the request and Facebook can not find the accesstoken anymore because of this.

Resources