Mavenlink API with node - node.js

I am trying to connect to mavenlink using node, but i keep getting an oauth2 validation error. Every solution online pertains to token generation for many users, but i just need to manipulate the data for use in an internal app. Does anyone have an example of oauth2 authentication for one user?

oauth2 authentication in this case is achieved with "Authorization": "Bearer key".toString('base64') inside of the headers option.
var https = require("https");
function printError (error) {
console.error(error);
}
key = 'oauth2 token';
var options = {
host: 'api.mavenlink.com',
path: '/api/v1/workspaces.json',
method: 'GET',
headers: {
"Content-type": "application/json",
"Authorization": "Bearer key".toString('base64')
}
};
var body = "";
var req = https.request(options, (res) => {
console.log('statusCode: ', res.statusCode);
console.log('headers: ', res.headers);
res.on('data', (d) => {
process.stdout.write(d);
});
res.on('data', function (chunks){
body += chunks;
});
res.on('end', function() {
if(res.statusCode == 200) {
try
{
//parse data
var massData = JSON.parse(body);
console.log(body);
} catch(error) {
//parse error
printError(error);
}
}
});
});

Related

How do I send a post request with a string in Node.js?

I am learning node, but can't figure out how to send a POST request with a string.
Here is my code:
const h = require('https');
h.post("https://VLang.johnstev111.repl.co", "print('test')")
This should do pretty much what you wish, we log the response and any errors.
I've set the content-type to 'text/plain', and you can change the data by setting the postData variable to whatever you wish.
const https = require('https');
// Put your post data here
const postData = "print(40 + 2)";
const options = {
hostname: 'VLang.johnstev111.repl.co',
method: 'POST',
headers: {
'Content-Length': postData.length
}
};
const req = https.request(options, (res) => {
console.log('Response: status:', res.statusCode);
console.log('Response: headers:', res.headers);
res.on('data', (d) => {
process.stdout.write("Response: " + d);
});
});
req.on('error', (e) => {
console.error("An error occurred:", e);
});
req.write(postData);
req.end();

Invalid Access Token in AWS Alexa Skill

Here is my code which I used for fetching the profile details using alexa skills but getting 401 issue along with below error
const GetMyEmailIntentHandler = {
canHandle(handlerInput) {
return (
handlerInput.requestEnvelope.request.type === 'IntentRequest' &&
handlerInput.requestEnvelope.request.intent.name === 'GetMyEmailIntent'
);
},
async handle(handlerInput) {
var apiaccessToken = handlerInput.requestEnvelope.context.System.apiAaccessToken;
var options = {
host : baseURL,
path : '/v2/accounts/~current/settings/Profile.email',
Accept: 'application/json',
method : 'GET',
headers:{
auth: 'Bearer ' + apiaccessToken
}
}
// making the https get call
var getReq = https.request(options, function(res) {
res.on('data', function(data) {
});
});
//end the request
getReq.end();
getReq.on('error', function(err){
});
return new Promise(resolve => {
getEmail(apiaccessToken => {
var speechText = 'Your accessToken fetched successfully';
resolve(
handlerInput.responseBuilder
.speak(speechText)
.reprompt(speechText)
.getResponse()
);
});
});
}
};
The error message that results is a 401 error that states that it's unable to determine the domain name. It also says I have an invalid token. However, I have provided the auth bearer token as a header inside the options object. I'm doing string concatenation to appear Bearer to the api token that comes in on the handlerInput.
2019-07-24T13:12:17.200Z c3b8254b-e773-43db-8a96-0ff0aeea1f5e Error handled: Unable to determine the domain name
2019-07-24T13:12:17.418Z c3b8254b-e773-43db-8a96-0ff0aeea1f5e
status code:============= 401
2019-07-24T13:12:17.419Z c3b8254b-e773-43db-8a96-0ff0aeea1f5e
INSIDE res.on:============= { code: 'ACCESS_DENIED', message: 'Invalid token' }
END RequestId: c3b8254b-e773-43db-8a96-0ff0aeea1f5e
I was getting the same. The only change I made is fetching the API endpoint from Context rather than hardcoding it.Below is the code that worked for me.
var profileAccessToken = 'Bearer ' + this.event.context.System.apiAccessToken;
var profileApiEndpoint = this.event.context.System.apiEndpoint;
const options = {
Host: profileApiEndpoint,
Accept: 'application/json',
Authorization: profileAccessToken
};
console.log(options);
var requestURLProfileEmail = profileApiEndpoint + "/v2/accounts/~current/settings/Profile.email";
console.log(requestURLProfile);
https.get(requestURLProfileEmail, options, (resp) => {
let data = '';
resp.on('data', (chunk) => {
data += chunk;
});
resp.on('end', () => {
console.log('Response profile info request-->' + data);
});
}).on("error", (err) => {
console.log(err);
this.emit(":tell", "There was an error processing your request.Please try again.");
});

Send POST Request via AWS Lambda in Node.js

I want to send a POST Request to Twilio when an Intent is called from my Alexa Skill. When testing the Code, there are no errors, but the Request doesn't seem to go through. Testing the POST Request in Postman works.
function postToTwilio() {
var http = require("https");
var postData = JSON.stringify({
'To' : '1234567',
'From': '1234546',
'Url': 'https://handler.twilio.com/twiml/blablabla',
});
var options = {
"method": "POST",
"hostname": "https://api.twilio.com",
"path": "/12344/Accounts/blablablablba/Calls.json",
"headers": {
"Authorization": "Basic blblablablablabla",
"Content-Type": "application/x-www-form-urlencoded",
}
};
var req = http.request(options, function (res) {
var chunks = [];
res.on("data", function (chunk) {
chunks.push(chunk);
});
res.on("end", function () {
var body = Buffer.concat(chunks);
console.log(body.toString());
});
});
req.write(postData);
req.end();
}
First of all, a request is a async call so you need to make alexa wait for the response.
To do that, you need to use async await process and using promises.
var postData = JSON.stringify({
'To' : '1234567',
'From': '1234546',
'Url': 'https://handler.twilio.com/twiml/blablabla',
});
var options = {
"method": "POST",
"hostname": "https://api.twilio.com",
"path": "/12344/Accounts/blablablablba/Calls.json",
"headers": {
"Authorization": "Basic blblablablablabla",
"Content-Type": "application/x-www-form-urlencoded",
}
};
function get(options) {
return new Promise(((resolve, reject) => {
const request = https.request(options, (response) => {
response.setEncoding('utf8');
let returnData = '';
if (response.statusCode < 200 || response.statusCode >= 300) {
return reject(new Error(`${response.statusCode}: ${response.req.getHeader('host')} ${response.req.path}`));
}
response.on('data', (chunk) => {
returnData += chunk;
});
response.on('end', () => {
resolve(JSON.parse(returnData));
});
response.on('error', (error) => {
reject(error);
});
});
request.write(postData)
request.end();
}));
}
Then, when you call this get function:
let response = await get(options)
I haven't tested as a whole but that is the base skeleton.
Let me know if that works.

How to make https call from Azure function?

I'm trying to create an Azure function using nodeJS, but when I make a call to an https API I get an error message.
Is it possible to make a HTTPS call from azure function?
Here is my code
const https = require('https');
const querystring = require('querystring');
module.exports = async function (context, req) {
if (req.query.accessCode || (req.body && req.body.accessCode)) {
var options = {
host: 'api.mysite.com',
port: 443,
path: '/oauth/access_token',
method: 'POST'
};
var postData = querystring.stringify({
client_id : '1234',
client_secret: 'xyz',
code: req.query.accessCode
});
var req = https.request(options, function(res) {
context.log('STATUS: ' + res.statusCode);
context.log('HEADERS: ' + JSON.stringify(res.headers));
res.on('data', function (chunk) {
context.log('BODY: ' + chunk);
});
});
req.on('error', function(e) {
context.log('problem with request: ' + e.message);
});
req.write(postData);
req.end();
context.res = {
status: 200,
body: "Hello " + (req.query.accessCode)
};
} else {
context.res = {
status: 400,
body: "Please pass a name on the query string or in the request body"
};
}
context.done();
};
I get an error but I do not see any error on the console, also if I comment all the https call it works fine and I can see the Hello message on the screen.
Two points to fix
Delete context.done();. See Azure document.
If your function uses the JavaScript async function declaration (available using Node 8+ in Functions version 2.x), you do not need to use context.done(). The context.done callback is implicitly called.
Rename your https.request like var myReq = https.request(options, function(res).
There's a name conflict causing error as function has a built-in req object declared.
It's possible, here is an example of how to make a request to an Azure AD v2 token endpoint (I'd assume you are trying to do something similar):
var http = require('https');
module.exports = function (context, req) {
var body = "";
body += 'grant_type=' + req.query['grant_type'];
body += '&client_id=' + req.query['client_id'];
body += '&client_secret=' + req.query['client_secret'];
body += '&code=' + req.query['code'];
const options = {
hostname: 'login.microsoftonline.com',
port: 443,
path: '/ZZZ920d8-bc69-4c8b-8e91-11f3a181c2bb/oauth2/v2.0/token',
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': body.length
}
}
var response = '';
const request = http.request(options, (res) => {
context.log(`statusCode: ${res.statusCode}`)
res.on('data', (d) => {
response += d;
})
res.on('end', (d) => {
context.res = {
body: response
}
context.done();
})
})
request.on('error', (error) => {
context.log.error(error)
context.done();
})
request.write(body);
request.end();
};
The difference is - the function is not async module.exports = function
I believe your issue is:
You should use the Node.js utility function util.promisify to turn error-first callback-style functions into awaitable functions.
link

The Auth0 /userinfo endpoint returns an unauthorized error

It's giving unauthorized as result error even when I pass the bearer token in Node.js application.
function getUser(authData){
var postData = querystring.stringify({ authorization: authData });
var options = {
host: 'pole.auth0.com',
method: 'GET',
path: '/userinfo'
};
//make request
httpsRequest(postData, options)
.then(function(result) {
// success
res.status(201).send({ 'success': true });
}, function(err) {
res.status(500).send({ 'success': false, 'reasonCode': "Internal error." });
});
};
Helper function:
function httpsRequest (data, options) {
return new Promise(function (resolve, reject) {
var req = https.request(options, function (res) {
var result = '';
console.log(options);
res.on('data', function (chunk) {
result += chunk;
});
res.on('end', function () {
console.log("https end result - " + result);
resolve(result);
});
res.on('error', function (err) {
reject(err);
})
});
// req error
req.on('error', function (err) {
reject(err);
});
//send request witht the postData form
req.write(data);
req.end();
});
}
The authData parameter has a string value like Bearer [token]. I'm using https.request to make the api request
Is there anything wrong on the code?
According to the /userinfo endpoint documentation you should be performing a GET HTTP request instead of a POST and additionally, you need to pass the access token in the Authorization header.
Update:
The problem is in how you're trying to pass the token in the authorization header.
You did not mentioned what you were using as HTTP client, but here's some sample code using request-promise as the Node HTTP client; this works fine.
var rp = require('request-promise');
var options = {
uri: 'https://[YOUR_TENANT].auth0.com/userinfo',
headers: {
'Authorization': 'Bearer [YOUR_ACCESS_TOKEN]'
}
};
rp(options)
.then(function (info) {
console.log('User information:', info);
})
.catch(function (err) {
// API call failed...
});
Update 2:
With Node.js built-in HTTP client:
const https = require('https');
var options = {
hostname: '[YOUR_TENANT].auth0.com',
port: 443,
path: '/userinfo',
method: 'GET',
headers: {
'Authorization': 'Bearer [YOUR_ACCESS_TOKEN]'
}
};
var req = https.request(options, (res) => {
res.on('data', (d) => {
process.stdout.write(d);
});
});
req.end();
req.on('error', (e) => {
console.error(e);
});
Again, the vital part is on how to pass the token in the correct header.

Resources