oAuth code exchange for secret token - node.js

I'm making an app that is supposed to use oAuth to authenticate players from the Blizzard servers, I want to access their character info.. and I can't figure out how to ask for the secret_token. I guess I'm doing my post request wrong below is the code I'm using
app.post('/', function(req, res) {
var code = req.body.code; //this is the code i get ounce the player is redirected back to my redirect_uri
var redirectUri = "https://localhost:3000/oauth_callback.html";
var scope = "wow.profile";
var key = "they client_id i was given";
var secret = "they secret I was given";
var grantType = "authorization_code";
var tokenUri = "https://us.battle.net/oauth/token";
var uriBody = "?client_id=" + key + "&client_secret=" + secret + "&grant_type=authorization_code&code=" + code + "&redirect_uri=" + redirectUri + "&scope=" + scope;
request({
url: tokenUri, //URL to hit
method: 'POST',
headers: {
'Content-Type': "application/x-www-form-urlencoded",
},
body: uriBody //Set the body as a string
}, function(error, response, body){
if(error) {
console.log(error);
} else {
console.log(response.statusCode, body);
}
});
so basically I'm getting the code making a post request to my server with it, and then triggering a post request to the blizzard server trying to exchange my code for an access token.
The error I get is:
401 '{"error":"unauthorized","error_description":"An Authentication object was not found in the SecurityContext"}'
I'm using Node.js & request.js to make the post, my guess is I'm not making a proper request post request?

I think body key is not acceptable in request.
Send data in json if content-type is JSON or form if content-type is x-www-form-urlencoded
Like this
request({
url: tokenUri, //URL to hit
method: 'POST',
headers: {
'Content-Type': "application/x-www-form-urlencoded",
},
form: uriBody //Set the body as a string
}, function(error, response, body){
if(error) {
console.log(error);
} else {
console.log(response.statusCode, body);
}
});

finally! here is how I got it to work!
qs = query-string.js library...
var token_params = qs.stringify({
client_id: key,
client_secret: secret,
code: code,
scope: scope,
grant_type: 'authorization_code',
redirect_uri: redirectUri
});
request('https://us.battle.net/oauth/token?' + token_params, function(error, response, body){
if (error) {
console.log(error);
} else {
console.log(body)
}
});

Related

API is successful with request but fails with axios

I was doing auth0's code grant flow with pkce and there was an api call for fetching tokens in auth0 docs like this -
var request = require("request");
var options = {
method: 'POST',
url: 'https://YOUR_DOMAIN/oauth/token',
headers: {'content-type': 'application/x-www-form-urlencoded'},
form: {
grant_type: 'authorization_code',
client_id: 'YOUR_CLIENT_ID',
code_verifier: 'YOUR_GENERATED_CODE_VERIFIER',
code: 'YOUR_AUTHORIZATION_CODE',
redirect_uri: 'https://YOUR_APP/callback'
}
};
request(options, function (error, response, body) {
if (error) throw new Error(error);
console.log(body);
});
Now this successfully works and gets tokens, but if I try to do same request with axios it fails and returns 401 unautorized error. Can anyone tell me what I am doing wrong? My guess is that I am not sending the body correctly.
const axios = require("axios");
async function getTokens() {
const body = {
grant_type: 'authorization_code',
client_id: 'YOUR_CLIENT_ID',
code_verifier: 'YOUR_GENERATED_CODE_VERIFIER',
code: 'YOUR_AUTHORIZATION_CODE',
redirect_uri: 'https://YOUR_APP/callback'
};
const headers = {'content-type': 'application/x-www-form-urlencoded'};
const data = axios.post("https://YOUR_DOMAIN/oauth/token", body, {headers});
console.log(data);
}
Thank you in advance for your help.

Unable to make request in node.js

I am using the following code in the controller by CCAvenue but I get an error
TypeError: request.on is not a function
Below is the code for the request
request.on('data', function (data) {
console.log("data is ----------------> " + data);
body += data;
encRequest = ccav.encrypt(body, workingKey);
console.log("Enc request " + encRequest);
formbody = '<form id="nonseamless" method="post" name="redirect" action="https://secure.ccavenue.com/transaction/transaction.do?command=initiateTransaction"/> <input type="hidden" id="encRequest" name="encRequest" value="' + encRequest + '"><input type="hidden" name="access_code" id="access_code" value="' + accessCode + '"><script language="javascript">document.redirect.submit();</script></form>';
});
request.on('end', function () {
response.writeHeader(200, {
"Content-Type": "text/html"
});
response.write(formbody);
response.end();
});
I am including the request using var request = require('request')
Edit:
request.post("https://secure.ccavenue.com/transaction/transaction.do?command=initiateTransaction", {
form: {
encRequest: encRequest,
access_code: accessCode
}
},
function (error, response, body) {
console.log(body);
});
I get a response in my body which is an html page. How do I send it back to the browser in sail.js framework ?
Edit 2 :
I've tried using sails.request method too but there is no response.
var payReq = {
url: "https://secure.ccavenue.com/transaction/transaction.do?command=initiateTransaction",
method: "POST",
headers: {
"Content-Type": "text/html"
// "Content-Type": 'application/json'
},
// data : {
// encRequest: encRequest,
// access_code: accessCode
// }
data : `encRequest=${encRequest}&access_code=${accessCode}`
}
sails.request(payReq);
I think you're using Request in an incorrect way.. this pattern you're using would work for the HTTP/HTTPS libraries. Here's a Request example.
var request = require('request');
var options = {
url: "https://httpbin.org/ip",
method: "get"
};
console.log('Requesting IP..');
request(options, function (error, response, body) {
if (error) {
console.error('error:', error);
} else {
console.log('Response: Headers:', response && response.headers);
}
});
The request.on('data' .. pattern is used by the Native HTTP and HTTPs libraries. examples would be here:
https://www.twilio.com/blog/2017/08/http-requests-in-node-js.html
This page includes examples using Request, HTTP, Axios.

Node JS Request Printing nothing in console

I'm making an post call using the nodejs requests module. However, the console.log statements seems to be not working for either the error or the response.body that I am trying to get.
My POST request needs the following headers -
Accept : "application/json"
Content-Type : "application/json"
Authorization : Basic + Base64Encoded(username+password)
The post body is something like this
Body:
{
"arg_1" : "a_string_key"
, "arg_2" : "a_string"
, "arg_3" : "a_string"
, "arg_4" : "some_value"
, "arg_5" : "some_string"
, "arg_6" : "<yyyy-mm-dd>"
, "arg_7" : "<yyyy-mm-dd>"
}
My code does nothing but send a POST request and checks if the response.statusCode ==200
Here is what I am doing
var int_user = "username";
var int_pass = "password";
var encoding = "base64"
var auth = "Basic" + new Buffer(int_user + int_pass).toString(encoding);
var headers = {
"Accept": "application/json",
"Content-Type": "application/json",
"Authorization": auth
}
var options = {
url: 'URL_I_WANT',
// method: 'POST',
headers: headers,
body : {
"arg_1": "a_string_key",
"arg_2": "a_string",
"arg_3": "a_string",
"arg_4": "some_value",
"arg_5": "some_string",
"arg_6": "<yyyy-mm-dd>",
"arg_7": "<yyyy-mm-dd>"
},
json: true
}
console.log('Before request');
request.post(options, function(error, response) {
if (error) {
console.log(error);
}
try {
if (!error && response.statusCode == 200) {
console.log(response.body);
console.log('Success');
}
} catch (error) {
console.log(error)
}
});
console.log('After request');
The code runs without any glitch and I get the before and after request console statements. However the statements inside the requests do not appear in the console, which means my request is not going through. I am not able to understand this. Shouldn't an error come if there is an issue with the request itself? Any if the request is failing, why isn't the error printed out?
This could be because your node process is auto-closed and it will exit before the async request to finishes (haven't looked into it but it might be something configurable). I've seen such set-up on repl.it for example.
To overcome this(if not configurable), you could wrap your code in an async function and use the request-promise to call await request.
var request = require('request-promise-native');
var int_user = "username";
var int_pass = "password";
var encoding = "base64"
var auth = "Basic" + new Buffer(int_user + int_pass).toString(encoding);
var headers = {
"Accept": "application/json",
"Content-Type": "application/json",
"Authorization": auth
}
var options = {
url: 'https://google.com',
method: 'POST',
headers: headers,
body : {
"arg_1": "a_string_key",
"arg_2": "a_string",
"arg_3": "a_string",
"arg_4": "some_value",
"arg_5": "some_string",
"arg_6": "<yyyy-mm-dd>",
"arg_7": "<yyyy-mm-dd>"
},
json: true
};
console.log('Before request');
async function main() {
try {
const response = await request.post(options);
if (response.statusCode === 200) {
console.log(response.body);
console.log('Success');
process.exit();
}
console.log(`Bad statusCode:${response.statusCode}`);
}
catch (error) {
console.log(error);
}
}
main();
you can check-out the code below
a link to the code above, working on repl.it

csrf token validation fail in post request while calling sap odata service

var Array = require('node-array');
var request = require("request");
username = "user24",
password = "",
auth = "Basic " + new Buffer(username + ":" + password).toString("base64");
var options = { method: 'GET',
url: "http://207.188.73.88:8000/sap/opu/odata/sap/ZTEE_SUGGEST_SRV/ZteeSuggestSet?$filter=Number eq 5 and Date eq datetime'2014-03-11T00%3A00%3A00'&$format=json",
headers:
{
i am fetching xcsrf token here
'x-csrf-token': 'fetch',
'content-type': 'application/json',
authorization: auth } };
request(options, function (error, response, body) {
if (error) throw new Error(error);
// console.log(response.headers['x-csrf-token']);
var token="'";
token+=response.headers['x-csrf-token'];
token+="'";
//console.log(token);
var options = { method: 'POST',
url: 'http://207.188.73.88:8000/sap/opu/odata/sap/ZTEE_TIME_SRV/ZTEERESERVESet',
and setting the csrf token here but it give me error that scrf token required or invalid
headers:
{
authorization: auth,
'x-csrf-token': token,
'content-type': 'application/json' },
body:
{ Time: 'time\'PT11H00M00S\'',
Date: 'datetime\'2014-03-11T00%3A00%3A00\'',
Location: 'AAJ',
Number: 3 },
json: true };
request(options, function (error, response, body) {
if (error) throw new Error(error);
// console.log(body);
here it shows that token rrequired but i am already setting that in header
console.log(response.headers['x-csrf-token']);
});
});
I had faced similar situation while working with SAP WEBIDE.
I had disabled the request for token and i was able to establish the connection with Odata services. I did something like this code snippet in my component.js file.
var oModel = new sap.ui.model.odata.ODataModel(this.getMetadata().getConfig().serviceUrl);
oModel.disableHeadRequestForToken = true;
serviceURL contained the URL to Odata Service.
You can try to disable the CSRF token request and check.

CSRF token validation failed in nodejs while posting data to odata service

var request = require('request');
var username = '';
var password = '';
var url = 'http://207.188.73.88:8000/sap/opu/odata/sap/ZTEE_TIME_SRV/ZTEERESERVESet(Time=time\'PT11H00M00S\',Date=datetime\'2014-03-11T00%3A00%3A00\',Location=\'TAJ\',Number=3)';
var auth = 'Basic ' + new Buffer(username + ':' + password).toString('base64');
// i am trying to post data to odata service but the problem is that i could not get valid token from get service to use it in the post method i am first send get method
request(
{
url: url,
headers: {
'Authorization': auth,
'x-csrf-token': 'Fetch',
},
},
function(error, response, body) {
console.log('JSON data ' + response);
console.log('body' + body);
// trying to get the token to use in post
console.log(response.headers);
request(
{
url: url,
headers: {
here it says invalid token
'Authorization': auth,
'X-CSRF-TOKEN': 'u6piLO58XoK6udOkQ5Naww==',
},
method: 'POST',
//Lets post the following key/values as form
form: {
Time: 'PT11H00M00S',
Date: '2014-03-11T00%3A00%3A00',
Location: 'TAJ',
Number: 3,
},
},
function(error, response, body) {
console.log(body);
},
);
},
);
I got the solution.
I was trying to do this with POSTMAN, and it was working fine.
The thing is that when i was asking for CSRF token it always gave me the same back.
But when i tried with node, every time was different. Then i realized that the cookie was missing.
And thats all, the solution is to send the cookie at least in POST requests.
The set-cookie of the "Fetch" request must be sent in the Post request as Cookie beside the x-csrf-token
I put the example in typescript, but in js doesnt change so much, the idea is the same.
The example is not the best case but is complete to figure out how it works
let headers = {
"Authorization": "Basic " + new Buffer(username + ":" + password).toString("base64"),
"Content-Type":"application/json",
"Accept":"application/json",
"x-csrf-token":"Fetch" // get CSRF Token for post or update
};
// if you are using session vars
if (req.session.headers && req.session.headers.cookie) {
headers['Cookie'] = req.session.headers.cookie;
} else {
req.session.headers = {}; // initialize as object
}
let opts = {
url: "https://{host}:{port}/sap/opu/odata/sap/MD_SUPPLIER_MASTER_SRV",
qs: params1, // params set before, not set in the example
headers: headers,
json: true,
}
request(opts, (error: any, response: any, body: any): any => {
if (!error && response.statusCode === 200) {
if (response.headers["set-cookie"]) {
req.session.headers.cookie = response.headers["set-cookie"]; // store Cookie in session
headers['Cookie'] = req.session.headers.cookie; // set in headers for the next call. I guess this is the part you missed
}
if (response.headers['x-csrf-token']) {
req.session.headers.csrf = response.headers['x-csrf-token']; // store csrf-token in session
headers['x-csrf-token'] = req.session.headers.csrf; // set in headers for the next call
}
let options: request.Options = {
url: "https://{host}:{port}/sap/opu/odata/sap/MD_SUPPLIER_MASTER_SRV/C_BusinessPartnerSupplierEdit",
method: 'POST',
headers: headers,
qs: params2, // params set before
json: true,
}
request(options, (error: any, response: any, body: any): any => {
res.json(body);
});
}
});
Regards

Resources