How to authenticate using appid and appsecret in nodejs using https request - node.js

Here is the sample code for my application. Why It's not working ?
Error:
"{"error":"unauthorized","error_description":"An Authentication object was not found in the SecurityContext"}"
var post_data = JSON.stringify({
'appid' : results.appid,
'appsecret': results.appsecret,
});
var url = serviceUrl+"/oauth-service/oauth/token?grant_type=client_credentials";
var post_options = {
host: url,
headers: {
'Content-Type': 'application/json'
},
data:post_data
};
const req = https.request(post_options, function(res) {
res.setEncoding('utf8');
res.on('data',function(chunk){
console.log(chunk);
});
});
req.write(post_data);
req.end();

From the HTTPS request side, you don't need to have data in post_options (the data is sent using write).
More importantly, you need to set the Content-Length header to Buffer.byteLength(post_data).
Also, the host (or hostname) field should contain just the hostname (e.g. www.facebook.com - no https:// is needed) and the rest of the URL (e.g. /oauth_service/...) should be put in the path field.
Here's an example adapted from the node.js docs. They only provide examples for http but it's mostly the same as for https:
const postData = JSON.stringify({
'msg': 'Hello World!'
});
const options = {
hostname: 'www.google.com',
path: '/upload',
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Content-Length': Buffer.byteLength(postData)
}
};
const req = https.request(options, (res) => {
console.log(`STATUS: ${res.statusCode}`);
console.log(`HEADERS: ${JSON.stringify(res.headers)}`);
res.setEncoding('utf8');
res.on('data', (chunk) => {
console.log(`BODY: ${chunk}`);
});
res.on('end', () => {
console.log('No more data in response.');
});
});
req.write(postData);
req.end();
Note that without specifying which service you're working with, it's impossible to say whether you're implementing the protocol correctly (e.g. whether the URL is correct, whether your request body is correct, etc.). So if you fix the Content-Length and things still don't work, please provide more information.

Related

Axios POST to URL without urlencoding reserved character

I'm using Axios to POST to an external service where the URL requires including multiple apostrophes. The receiving service does not decode the URL of the received request, forcing us to figure out a way to POST to an unencoded URL.
I've not been able to discern any accessible way in which we could accomplish this.
const response = await axios.post("https://foo.bar/Company('ACME')", body, {
headers: {
Authorization: this.authHeader,
'Content-Type': 'application/json'
}
})
The crux of the issue is having the URL include Company('ACME') without the apostrophes being URL-encoded to %27.
I've figured this to be possible with the native HTTPS module, but I'd like to see if this couldn't be accomplished with Axios (or a similar library).
const https = require('https');
const data = JSON.stringify({
company: 'Acme Corporation'
});
const options = {
"hostname": "foo.bar",
"path": "/Company('ACME')",
"method": "POST",
"headers": {
"Content-Type": "application/json",
"Content-Length": data.length
}
};
const req = https.request(options, (res) => {
let data = '';
console.log('Status Code:', res.statusCode);
res.on('data', (chunk) => {
data += chunk;
});
res.on('end', () => {
console.log('Body: ', JSON.parse(data));
});
}).on("error", (err) => {
console.log("Error: ", err.message);
});
req.write(data);
req.end();
Is there any way to accomplish this with Axios or a similiar library?

NodeJS request get return me html code instead of json

I'm trying to get get a json from a get request it's work in python but in NodeJs that display me the html code source of the page
this is my code :
app.get("/well", function(request, response) {
const req = require('request');
const options = {
url: 'https://swarmmanager.francecentral.cloudapp.azure.com:3000',
method: 'GET',
headers: {
'Accept': 'application/json',
},
agentOptions: {
ca: fs.readFileSync("public/IdaktoPKIRootCA.crt")
}
};
req(options, function(err, res, body) {
console.log(body);
});
});
and this is another version but same problem:
app.get("/well", function(request, response) {
g_CnieOidcAddr = 'https://swarmmanager.francecentral.cloudapp.azure.com:3000';
const options = {
hostname: 'swarmmanager.francecentral.cloudapp.azure.com',
port: 3000,
method: 'GET',
headers: {
'Accept': 'application/json',
},
ca: fs.readFileSync("public/IdaktoPKIRootCA.crt")
};
const req = https.request(options, (res) => {
console.log('statusCode:', res.statusCode);
console.log('headers:', res.headers);
res.on('data', (d) => {
process.stdout.write(d);
});
});
req.on('error', (e) => {
console.error(e);
});
req.end();
});
i try to do it in python and it's work find that return me a json:
headers = {'Accept': 'application/json'}
r = requests.get(g_CnieOidcAddr + '/.well-known/openid-configuration', params={}, headers = headers, verify='./IdaktoPKIRootCA.crt')
print (r.text)
if anyone has an idea i'm a taker ^^ thanks for reading.
ok that work find i just forgot something at the end of the url so if you come to this page the 2 codes work find to to a request

Use native Node.JS code to get a WSO2 access_token

I have been trying to use native Node.JS code in Node 8 to get an access token from WSO2 with my client ID and client secret.
I receive the following error: Unsupported Client Authentication Method!
Here is my code:
const querystring = require('querystring');
const https = require('https');
var postData = querystring.stringify({
'grant_type' : 'client_credentials'
});
var options = {
hostname: 'api.somedomain.com',
port: 443,
path: '/token',
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': postData.length
}
};
var req = https.request(options, (res) => {
console.log('statusCode:', res.statusCode);
console.log('headers:', res.headers);
res.on('data', (data) => {
process.stdout.write(data);
});
});
req.on('error', (err) => {
console.error(err);
});
req.write(postData);
req.end();
When I attempt to include another option parameter of 'auth' for the client ID and client secret then it tells me "TypeError: First argument must be a string, Buffer, ArrayBuffer, Array, or array-like object."
Any help on how to make this work is greatly appreciated.
Looks like you are missing the Authorization header with the request. I'm no expert on javascript/node but the token generation works after adding the Authorization header in the headers section as below. I have used localhost for testing purpose.
var auth = 'Basic ' + Buffer.from("nM_ftrK2pjoBW4JofE21xI1cP0Ya" + ':' + "jmFJIgC5QMDkU_HxQKiDUbp5UAca").toString('base64');
var options = {
hostname: 'localhost',
port: 8243,
path: '/token',
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': postData.length,
'Authorization': auth
}
};
The correct value (Authorization : Basic Base64(consumer-key:consumer-secret)) should be passed in with the token request when invoking the token endpoint to get the access_token.

make a post request with in node.js application

I've a node.js service with /api/authenticate endpoint. I can call this service successfully from POSTMAN with 'username' and 'password' as input (body parameters). How do I call the same services from another node.js server?
With postman I get,
body: {name: 'xxxxxx', password: 'xxxxxx' }
headers: { 'content-type': 'application/x-www-form-urlencoded',
host: 'xx.xx.xx.xx:xxxx',
connection: 'close',
'content-length': '0' }
POST /api/authenticate 200 1.336 ms - 72
Following is another nodejs application ... which makes a successful request call but doesn't have any body parameters (username and password) when it reaches to the authentication server api.
var my_http = require('http');
app.get('/makeacall', function(req, res) {
var output = '';
var options = {
body: { name: 'xxxxxx', password: 'xxxxxx' },
method: 'POST',
host: 'xx.xx.xx.xx',
port: 'xxxx',
path: '/api/authenticate',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
};
console.log('before request');
var req = my_http.request(options, function(response) {
console.log('response is: ' + response);
console.log('Response status code: ' + response.statusCode);
response.on('data', function(chunk) {
console.log('Data ..');
output += chunk;
});
response.on('end', function(chunk) {
console.log('Whole Data ..' + output);
});
});
req.on('error', function(err) {
console.log('Error: ' + err);
});
req.end();
console.log('444');
res.send({ message: 'View record message'});
});
From this nodejs application I get empty body on the server.
body: {}
headers: { 'content-type': 'application/x-www-form-urlencoded',
host: 'xx.xx.xx.xx:xxxx',
connection: 'close',
'content-length': '0' }
POST /api/authenticate 200 1.336 ms - 72
What am I missing? Any help is appreciated.
Using stock http library of NodeJS doesn't allow you to use that syntax.
Take a look at RequestJS as a much simpler solution. It will make your life a lot easier and allow you to use the syntax you want.
This is the solution to do it with stock Node.
https://nodejs.org/api/http.html#http_http_request_options_callback
Relevant Parts:
var postData = querystring.stringify({
'msg' : 'Hello World!'
});
And then, at the end:
// write data to request body
req.write(postData);
req.end();
But use a library unless you absolutely can't.
Are you trying to get the posted data from a form/etc?
Try using express.
npm install express -save
You can get posted data from a url with the ff:
app.post('*', function(request, response){
var post = {};
if(Object.keys(request.body).length){
for(var key in request.body){
post[key] = request.body[key];
console.log(key+'=>'+post[key];
}
}
});

Updating post http request length in node.js

I'm using node.js to post a http request. the code works with if i define my post data ahead of the 'options' field, but if I initially set my post_data string to empty and update it later it doesn't pick up the new length. How would I get it to do that ? I'm looking to send multiple posts of varying lengths to the same place in a loop so need to be able to do this.
var post_data=''; //if i set my string content here rather than later on it works
var options = {
host: '127.0.0.1',
port: 8529,
path: '/_api/cursor',
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Content-Length': post_data.length
}
};
var req = http.request(options, function(res) {
res.setEncoding('utf8');
res.on('data', function (chunk) {
console.log('BODY: ' + chunk);
});
});
req.on('error', function(e) {
console.log('problem with request: ' + e.message);
});
post_data = 'a variable length string goes here';//the change in length to post_data is not //recognised
req.write(post_data);
req.end();
'Content-Length': post_data.length
You ran this before setting post_data.
If you want to set post_data after creating the object, you'll need to set it manually later:
options.headers['Content-Length'] = post_data.length;
Note that you must set that before calling http.request().
Posting data is a matter of sending a query string (just like the way you would send it with an URL after the ?) as the request body.
This also requires to declare Content-Type and Content-Length values so the server knows how to interpret the data.
var querystring = require('querystring');
var data = querystring.stringify({
username: yourUsernameValue,
password: yourPasswordValue
});
var options = {
host: 'my.url',
port: 80,
path: '/login',
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': data.length
}
};
var req = http.request(options, function(res) {
res.setEncoding('utf8');
res.on('data', function (chunk) {
console.log("body: " + chunk);
});
});
req.write(data);
req.end();
You need to replace:
'Content-Length': post_data.length
for:
'Content-Length': Buffer.byteLength(post_data, 'utf-8')
See https://github.com/strongloop/express/issues/1870

Resources