Im trying to construct an OAuth2 request to the Box API. The example POST request they give as a guideline is a bit ambiguous to me as I am recently learning backend development. The example is as follows:
POST /token
Content-Type: application/x-www-form-urlencoded
grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer&
assertion=<JWT>&
client_id=<client_id>&
client_secret=<client_secret>
Official Docs:
https://box-content.readme.io/docs/app-auth
The way I attempted to do this is as follows:
var boxHeaders = {
'Content-Type': 'application/x-www-form-urlencoded'
};
var boxOptions = {
url: 'https://api.box.com/oauth2/token',
method: 'POST',
headers: boxHeaders,
form: {
'grant_type': 'urn:ietf:params:oauth:grant-type:jwt-bearer',
'assertion': boxtoken,
'client_id': 'myclientid',
'client_secret': 'myclientsecret'
}
};
request.post(boxOptions, function(err, response, body) {
console.log(body);
});
I get the following error:
{
"error":"invalid_request",
"error_description":"Invalid grant_type parameter or parameter missing"
}
Obviously the grant type is incorrect but I have no idea how to go about constructing the string based on the Box API example. If anyone can help and even expose me to some good articles or tutorials on how to do this, that would be great!
Thank you.
I just struggled with this myself. I was able to get this to work by moving everything you currently have in boxOptions.form into the request body.
For example:
var boxHeaders = {
'Content-Type': 'application/x-www-form-urlencoded'
};
var boxOptions = {
url: 'https://api.box.com/oauth2/token',
method: 'POST',
headers: boxHeaders
};
var form = {
grant_type:'urn:ietf:params:oauth:grant-type:jwt-bearer',
client_id: 'id',
client_secret: 'secret',
assertion: boxtoken
};
var request = https.request(boxOptions, function(response) {
// do stuff
});
request.write(querystring.stringify(form));
request.end();
Hope this helps. Unfortunately, I'm not familiar enough with the request library to provide an example using it.
Related
So I currently have the functioning code in python
import requests
import json
address = "*address here*"
viewkey = "*viewkey here*"
headers = {'content-type': 'application/json'}
url = "https://api.mymonero.com:8443/get_address_txs"
data = {"address":address,"view_key":viewkey}
data = json.dumps(data)
response = requests.post(url, data=data, headers=headers)
print(response.text)
And I tried to move to nodejs to integrate it with another program I have written
var request = require('request');
var options = {
url: 'https://api.mymonero.com:8443/get_address_txs',
headers: {'content-type': 'application/json'},
data: JSON.stringify({
address:"address",
viewkey:"viewkey"
})
};
request.post(options,function(error, response, body) {
console.log(body);
})
I assumed the code would be identical but clearly not I get an error from the server with the second segment of code. Please could someone help me migrate this?
Note: I know requests in python has a json attribute I have written it in python this way for clarity.
For the record the response I get from the javascript is:
{
"Error": "Problems parsing JSON"
}
When I get from python:
{
"total_received": "152840132538",
"scanned_height": 2589644,
"scanned_block_height": 1320308,
"start_height": 2586111,
...
}
Do not stringify your msg. That should be it.
In your json, in python the key is view_key, in javascript it's view key.
Also, the request library doesn't have a data key in it's options. You can use body to set the raw body. If you use json, the body will be the son representation of the dict you pass, and the Content-Type header is set for you .
Right I'm an accidental genius I have no idea why my current method wasn't working but the solution I came up with was:
var request = require('request');
var options = {
url: 'https://api.mymonero.com:8443/get_address_txs',
headers: {'content-type': 'application/json'},
json: {
"address":"*address*",
"view_key":"*viewkey*"
}
};
request.post(options,function(error, response, body) {
console.log(body);
})
No idea why it works but hey that's life thank you so much for your suggestions.
This is my sample request:
var header = new Headers({
'Platform-Version': 1,
'App-Version': 1,
'Platform': 'FrontEnd'
});
var myInit = {
method : 'GET',
headers: header,
mode : 'no-cors',
cache : 'default'
}
fetch('http://localhost:3000/api/front_end/v1/login', myInit)
.then(res => {
console.log(res.text())
})
When I debug, I see that this request is sent successfully to server, but server hasn't received header params (in this case is Platform-Version, App-Version and Platform). Please tell me which part do I config wrong.
thanks
You are using it correctly, but you have to tell your backend service to allow custom headers (X-). For example, in PHP:
header("Access-Control-Allow-Headers: X-Requested-With");
Also, your custom headers should be prefixed with X-. So you should have:
'X-Platform-Version': '1'
And one last thing, your mode needs to be cors.
You can see that standard headers are being sent with the following code. take a look at the network tab to see the standard request headers.
var header = new Headers();
// Your server does not currently allow this one
header.append('X-Platform-Version', 1);
// You will see this one in the log in the network tab
header.append("Content-Type", "text/plain");
var myInit = {
method: 'GET',
headers: header,
mode: 'cors',
cache: 'default'
}
fetch('http://localhost:3000/api/front_end/v1/login', myInit)
.then(res => {
console.log(res.text())
});
The instagram "server side workflow" for authenticating a user and giving them a session access token doesn't work. First part works in that I can get a code back from here:
https://api.instagram.com/oauth/authorize/?client_id=CLIENT-ID&redirect_uri=REDIRECT-URI&response_type=code
However, when posting this code to
https://api.instagram.com/oauth/access_token
in order to obtain the access token, it just response with "YOU MUST PROVIDE A CLIENT ID", even though I have provided this as part of the form data - the same client id I used to get the code in the first place!
Here is the code I am using:
getIgToken: function (igCode) {
let data = {
client_id: config.imported.instagram.client_id,
client_secret: config.imported.instagram.client_secret,
grant_type: 'authorization_code',
redirect_uri: 'http://localhost:5000/app/scrape',
code: igCode
}
return $http({
method: 'POST',
url: 'https://api.instagram.com/oauth/access_token',
data: data,
headers: {
"Content-Type": "application/x-www-form-urlencoded",
},
})
}
Apparently others have reported problems with posting the data as json, which have then been resolved by using "application/x-www-form-urlencoded" - however this doesn't seem to work either now.
Here is the exact error message returned:
{error_type: "OAuthException", code: 400, error_message: "You must provide a
client_id"}
code:400
error_message:"You must provide a client_id"
error_type:"OAuthException"
grant_type should be 'authorization_code'
convert the data object to json format , try
data: JSON.stringify(data),
your code will look like this
getIgToken: function (igCode) {
let data = {
client_id: config.imported.instagram.client_id,
client_secret: config.imported.instagram.client_secret,
grant_type: 'authorisation_code',
redirect_uri: 'http://localhost:5000/app/scrape',
code: igCode
}
var jsonData= JSON.stringify(data)
return $http({
method: 'POST',
url: 'https://api.instagram.com/oauth/access_token',
data: jsonData,
headers: {
"Content-Type": "application/x-www-form-urlencoded",
},
})
}
I just recently started learning MEAN stack so forgive me if this seems like a really dumb question. My problem is as follows:
On the client side (controller.js) I have,
$http({
method : 'POST',
url : '/root',
// set the headers so angular passing info as form data (not request payload)
headers : { 'Content-Type': 'application/x-www-form-urlencoded' },
data : {
type:'root',
username:$scope.rEmail,
password:$scope.rPassword
}
})
On the server side I have,
app.post('/root', function(req, res) {
console.log(req.body);
console.log(req.body.username);
});
My console log shows:
17 Nov 21:39:04 - [nodemon] starting `node server/server.js`
{ '{"type":"root","username":"testUserName","password":"testPassword"}': '' }
undefined
I would imagine req.body.username to give me testUserName but I get undefined. The JSON format I am getting is slightly weird. Can anyone help me out this one? I did some reading and tried using body-parser and went through angular js $http.post documentation but didn't find anything that would help me out.
I imagine the problem is at:
{ '{"type":"root","username":"testUserName","password":"testPassword"}': '' }
but I cant seem to figure out how I would pass the data from $http.post in my angular controller so that I would just get my request in identifier:value format.
Nevermind, I figured it out. Seems like I needed a break from coding.
headers : { 'Content-Type': 'application/x-www-form-urlencoded' }
to
headers : { 'Content-Type': 'application/json' }
fixed the problem.
Try my source code below:
$http({
method : 'POST',
url : '/root',
// set the headers so angular passing info as form data (not request payload)
headers : { 'Content-Type': 'application/x-www-form-urlencoded' },
data : {
type:'root',
username:$scope.rEmail,
password:$scope.rPassword
},
transformRequest: function(obj) {
var str = [];
for(var p in obj){
str.push(encodeURIComponent(p) + '=' + encodeURIComponent(obj[p]));
}
return str.join('&');
}
})
$http({
method : 'POST',
url : '/root',
// set the headers so angular passing info as form data (not request payload)
headers : { 'Content-Type': 'application/x-www-form-urlencoded' },
params : {
type:'root',
username:$scope.rEmail,
password:$scope.rPassword
}
})
try it with 'params', maybe it won't work but try it :P
I've tried with "params" instead of "data" and worked ok, and doesn't matter if headers are "application/x-www-form-urlencoded" or "application/json"
But using "application/json" works with request.query.param1 on node.
I have some old code that is making an AJAX POST request through jQuery's post method and looks something like this:
$.post("/foo/bar", requestData,
function(responseData)
{
//do stuff with response
}
requestData is just a javascript object with some basic string properties.
I'm in the process of moving our stuff over to use Angular, and I want to replace this call with $http.post. I came up with the following:
$http.post("/foo/bar", requestData).success(
function(responseData) {
//do stuff with response
}
});
When I did this, I got a 500 error response from the server. Using Firebug, I found that this sent the request body like this:
{"param1":"value1","param2":"value2","param3":"value3"}
The successful jQuery $.post sends the body like this:
param1=value1¶m2=value2¶m3=value3
The endpoint I am hitting is expecting request parameters and not JSON. So, my question is is there anyway to tell $http.post to send up the javascript object as request parameters instead of JSON? Yes, I know I could construct the string myself from the object, but I want to know if Angular provides anything for this out of the box.
I think the params config parameter won't work here since it adds the string to the url instead of the body but to add to what Infeligo suggested here is an example of the global override of a default transform (using jQuery param as an example to convert the data to param string).
Set up global transformRequest function:
var app = angular.module('myApp');
app.config(function ($httpProvider) {
$httpProvider.defaults.transformRequest = function(data){
if (data === undefined) {
return data;
}
return $.param(data);
}
});
That way all calls to $http.post will automatically transform the body to the same param format used by the jQuery $.post call.
Note you may also want to set the Content-Type header per call or globally like this:
$httpProvider.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded; charset=UTF-8';
Sample non-global transformRequest per call:
var transform = function(data){
return $.param(data);
}
$http.post("/foo/bar", requestData, {
headers: { 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'},
transformRequest: transform
}).success(function(responseData) {
//do stuff with response
});
If using Angular >= 1.4, here's the cleanest solution I've found that doesn't rely on anything custom or external:
angular.module('yourModule')
.config(function ($httpProvider, $httpParamSerializerJQLikeProvider){
$httpProvider.defaults.transformRequest.unshift($httpParamSerializerJQLikeProvider.$get());
$httpProvider.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded; charset=utf-8';
});
And then you can do this anywhere in your app:
$http({
method: 'POST',
url: '/requesturl',
data: {
param1: 'value1',
param2: 'value2'
}
});
And it will correctly serialize the data as param1=value1¶m2=value2 and send it to /requesturl with the application/x-www-form-urlencoded; charset=utf-8 Content-Type header as it's normally expected with POST requests on endpoints.
From AngularJS documentation:
params – {Object.} – Map of strings or objects which
will be turned to ?key1=value1&key2=value2 after the url. If the
value is not a string, it will be JSONified.
So, provide string as parameters. If you don't want that, then use transformations. Again, from the documentation:
To override these transformation locally, specify transform functions
as transformRequest and/or transformResponse properties of the config
object. To globally override the default transforms, override the
$httpProvider.defaults.transformRequest and
$httpProvider.defaults.transformResponse properties of the
$httpProvider.
Refer to documentation for more details.
Use jQuery's $.param function to serialize the JSON data in requestData.
In short, using similar code as yours:
$http.post("/foo/bar",
$.param(requestData),
{
headers:
{
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
}
}
).success(
function(responseData) {
//do stuff with response
}
});
For using this, you have to include jQuery in your page along with AngularJS.
Note that as of Angular 1.4, you can serialize the form data without using jQuery.
In the app.js:
module.run(function($http, $httpParamSerializerJQLike) {
$http.defaults.transformRequest.unshift($httpParamSerializerJQLike);
});
Then in your controller:
$http({
method: 'POST',
url: myUrl',
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
data: myData
});
This might be a bit of a hack, but I avoided the issue and converted the json into PHP's POST array on the server side:
$_POST = json_decode(file_get_contents('php://input'), true);
I have problems as well with setting custom http authentication because $resource cache the request.
To make it work you have to overwrite the existing headers by doing this
var transformRequest = function(data, headersGetter){
var headers = headersGetter();
headers['Authorization'] = 'WSSE profile="UsernameToken"';
headers['X-WSSE'] = 'UsernameToken ' + nonce
headers['Content-Type'] = 'application/json';
};
return $resource(
url,
{
},
{
query: {
method: 'POST',
url: apiURL + '/profile',
transformRequest: transformRequest,
params: {userId: '#userId'}
},
}
);
I hope I was able to help someone. It took me 3 days to figure this one out.
Modify the default headers:
$http.defaults.headers.post["Content-Type"] = "application/x-www-form-urlencoded;charset=utf-8";
Then use JQuery's $.param method:
var payload = $.param({key: value});
$http.post(targetURL, payload);
.controller('pieChartController', ['$scope', '$http', '$httpParamSerializerJQLike', function($scope, $http, $httpParamSerializerJQLike) {
var data = {
TimeStamp : "2016-04-25 12:50:00"
};
$http({
method: 'POST',
url: 'serverutilizationreport',
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
data: $httpParamSerializerJQLike(data),
}).success(function () {});
}
]);
Quick adjustment - for those of you having trouble with the global configuration of the transformRequest function, here's the snippet i'm using to get rid of the Cannot read property 'jquery' of undefined error:
$httpProvider.defaults.transformRequest = function(data) {
return data != undefined ? $.param(data) : null;
}
You can also solve this problem without changing code in server, changing header in $http.post call and use $_POST the regular way. Explained here: http://victorblog.com/2012/12/20/make-angularjs-http-service-behave-like-jquery-ajax/
I found many times problematic behavior of this whole. I used it from express (without typings) and the bodyParser (with the dt~body-parser typings).
I didn't try to upload a file, instead simply to interpret a JSON given in a post string.
The request.body was simply an empty json ({}).
After a lot of investigation finally this worked for me:
import { json } from 'body-parser';
...
app.use(json()); <-- should be defined before the first POST handler!
It may be also important to give the application/json content type in the request string from the client side.
Syntax for AngularJS v1.4.8 + (v1.5.0)
$http.post(url, data, config)
.then(
function (response) {
// success callback
},
function (response) {
// failure callback
}
);
Eg:
var url = "http://example.com";
var data = {
"param1": "value1",
"param2": "value2",
"param3": "value3"
};
var config = {
headers: {
'Content-Type': "application/json"
}
};
$http.post(url, data, config)
.then(
function (response) {
// success callback
},
function (response) {
// failure callback
}
);