Getting LinkedIn access token through http request on node.js server - node.js

I am following the Authorization Code Flow (3-legged OAuth) documentation and I am now at step 3 where I need to use the authorization code in order to recieve an access token from LinkedIn. In the project I am using node.js, typescript and the node-fetch library. The following function creates a body with content type x-www--form-urlencoded since this is content type which LinkedIn require.
async function GetAccessToken(data: any) {
let body: string | Array<string> = new Array<string>();
for (let property in data) {
let encodedKey = encodeURIComponent(property);
let encodedValue = encodeURIComponent(data[property]);
body.push(encodedKey + "=" + encodedValue);
}
body = body.join("&");
const response = await fetch("https://www.linkedin.com/oauth/v2/accessToken", {
method: 'POST',
headers: {'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'},
body: body
}).then((res: any) => {
console.log("Result", res);
});
return response;
}
I do not recieve any errors and the response status is 200 but the response values I recieve are:
size: 0,
timeout: 0,
and what LinkedIn promise is:
access_token
expires_in
When I post the url with my parameters using postman the request goes through and I recieve the correct data which indicates the problem lies within my request function and not my values.
Any help is appreciated!

You need add all headers from postman
const urlencoded = new URLSearchParams();
urlencoded.append("client_id", env.LINKEDIN_CLIENT_ID);
urlencoded.append("client_secret",env.LINKEDIN_CLIENT_SECRET);
urlencoded.append("grant_type", "authorization_code");
urlencoded.append("code", code);
urlencoded.append(
"redirect_uri",
"http://localhost:3000/api/auth/linkedin-custom"
);
const accessTokenPromise = await fetch(
"https://www.linkedin.com/oauth/v2/accessToken",
{
method: "POST",
headers: {
"Content-Type": "application/x-www-form-urlencoded",
},
body: urlencoded,
}
);

Related

Not Able to get request body as desired

I am working on MERN stack and I have made an api for registering users. I am using axios to send request this is what i am doing with axios inside react
const body = {
'phone': phoneData.phoneNumber, \\ phoneData is a state
'lastName': 'Flintstone'
}
await axios({
method : 'post',
url : 'http://localhost:8000/userapi/register',
data : JSON.stringify(body),
header : {'Content-Type': 'application/json'}
});
After this in NodeJS i am trying to print req.body on the console an this is what i am receiving
{ '{"phone":"7428868740","lastName":"Flintstone"}': '' }
instead of that i want req.body to store
{ phone:"7428868740",lastName:"Flintstone" }
This is my route that is getting triggered
app.post('/userapi/register', (req,res) =>{
console.log(req.body);
/* rest code to register user */
}
With Axios, you don't need to call JSON.stringify, just send the object and the server will receive it correctly.
const body = {
'phone': phoneData.phoneNumber, // phoneData is a state
'lastName': 'Flintstone'
}
await axios({
method : 'post',
url : 'http://localhost:8000/userapi/register',
data : body,
headers : {'Content-Type': 'application/json'}
});
See documentation here
On the server-side, make sure there is a middleware to parse requests in JSON format.
You can
const config = {
header: {
"Content-Type": "application/json",
},
};
const res = await axios.post(url,body,config)

node-fetch send post request with body as x-www-form-urlencoded

i want to send a post request using node-fetch with a body payload encoded in the x-www-form. I tried this code but unfortunately it doesnt work:
paypalSignIn = function(){
var username = process.env.PAYPALID;
var password = process.env.PAYPALSECRET;
var authContent = 'Basic '+base64.encode(username + ":" + password);
fetch('https://api.sandbox.paypal.com/v1/oauth2/token', { method: 'POST',
headers: {
'Accept': 'application/json',
'Accept-Language' :"en_US",
'Authorization': authContent,
'Content-Type': 'application/x-www-form-urlencoded'
},
body: 'grant_type=client_credentials' })
.then(res => res.json()) // expecting a json response
.then(json => console.log(json));
}
I'm not sure if this way is possible but i need to use this standard for die paypal api.
I'm getting statu code 400 with error
grant_type is null
Thx
I don't know if this is the only error, but at the very least you need a space between the word Basic and the encoded username/password.
Next time you ask a question, also post what your script returned. I'm guessing it was a 401 error in this case.
I used the PayPal sandbox today, here is how I managed to get my access token and a successful response (and also answering the OP's question about sending application/x-www-form-urlencoded POST requests with data) =>
I did it with node-fetch but the plain fetch API should work the same.
import fetch from "node-fetch";
export interface PayPalBusinessAccessTokenResponseInterface {
access_token: string;
}
export interface PayPalClientInterface {
getBusinessAccessToken: (
clientId: string,
clientSecret: string
) => Promise<PayPalBusinessAccessTokenResponseInterface>
}
const paypalClient: PayPalClientInterface = {
async getBusinessAccessToken(
clientId: string,
clientSecret: string
): Promise<PayPalBusinessAccessTokenResponseInterface> {
const params = new URLSearchParams();
params.append("grant_type", "client_credentials");
const paypalAPICall = await fetch(
"https://api-m.sandbox.paypal.com/v1/oauth2/token",
{
method: "POST",
body: params,
headers: {
"Authorization": `Basic ${Buffer.from(clientId + ":" + clientSecret).toString('base64')}`
}
}
);
const paypalAPIRes = await paypalAPICall.json();
return paypalAPIRes;
}
};
export default paypalClient;

Angular consumes express web api , bad request

My angular app consumes a nodejs webapi :
var header = {
headers: new HttpHeaders()
.set('Authorization', `Bearer ${this.token}`)
}
var url="http://localhost:3000/user/deleteTodoFromUser/"+idUser+"/"+idTodo;
return this.http.put(url,"",header);
my api :
**router.put('/deleteTodoFromUser/:id/:idTodo', passport.authenticate('bearer'), (req, res) => {**
User.findByIdAndUpdate(req.params.id,{ $pull:{todos:{$in:[req.params.idTodo]}}},{new:true},(err, usr) => {
if (err) {
res.send(err);
}
if(usr)
{
res.send(usr);
}
else
{
res.status(400).send("bad request");
}
**My api works properly in postman **
** CORS are enabled **
in angular doesn't, it returns 400 (bad request )
let params = new HttpParams();
params = params.append('id', idUser);
params = params.append('idTodo', idTodo);
this.http.put(url, "", { headers: headers, params: params });
when I add params parameter in the request , It becomes like that
http://localhost:3000/user/deleteTodoFromUser/?id=5dfa958e98710030207952cc&idTodo=5dfa976ea4ea1d31f8919ee5
but the api waits the request like that :
http://localhost:3000/user/deleteTodoFromUser/5dfa958e98710030207952cc/5dfa976ea4ea1d31f8919ee5
the difference is my api waits the request id without id?= and idTodo?=
and I want it like that
400 Bad Request, Whatever the endpoint is expecting, it's not getting it.
Seems that there is an issue while passing params to your API or the token value sent to your API is invalid.
This is another way to send parameters to your API instead of Appending them to the URL
const headers = new HttpHeaders()
.set('Authorization', `Bearer ${this.token}`);
let params = new HttpParams();
params = params.append('id', idUser);
params = params.append('idTodo', idTodo);
this.http.put(url, "", { headers: headers, params: params });
If it's not the case try to make a call using real parameters value and a valid token that works in Postman in order to detect the root cause of the error that you are getting.

Making a POST request using puppeteer with JSON payload

I'm trying to make a POST request using puppeteer and send a JSON object in the request, however, I'm getting a timeout... if I'm trying to send a normal encoded form data that at least a get a reply from the server of invalid request...
here is the relevant part of the code
await page.setRequestInterception(true);
const request = {"mac": macAddress, "cmd": "block"};
page.on('request', interceptedRequest => {
var data = {
'method': 'POST',
'postData': request
};
interceptedRequest.continue(data);
});
const response = await page.goto(configuration.commandUrl);
let responseBody = await response.text();
I'm using the same code to make a GET request (without payload) and its working
postData needs to be encoded as form data (in the format key1=value1&key2=value2).
You can create the string on your own or use the build-in module querystring:
const querystring = require('querystring');
// ...
var data = {
'method': 'POST',
'postData': querystring.stringify(request)
};
In case you need to submit JSON data:
'postData': JSON.stringify(request)
If you are sending json, you need to add "content-type": "application/json". If you don't send it you can receive an empty response.
var data = {
method : 'POST',
postData: '{"test":"test_data"}',
headers: { ...interceptedRequest.headers(), "content-type": "application/json"}
};
interceptedRequest.continue(data);

Podio API addItem call

I'm trying to implement https://developers.podio.com/doc/items/add-new-item-22362 Podio API addItem call in a nodejs module. Here is the code:
var _makeRequest = function(type, url, params, cb) {
var headers = {};
if(_isAuthenticated) {
headers.Authorization = 'OAuth2 ' + _access_token ;
}
console.log(url,params);
_request({method: type, url: url, json: true, form: params, headers: headers},function (error, response, body) {
if(!error && response.statusCode == 200) {
cb.call(this,body);
} else {
console.log('Error occured while launching a request to Podio: ' + error + '; body: ' + JSON.stringify (body));
}
});
}
exports.addItem = function(app_id, field_values, cb) {
_makeRequest('POST', _baseUrl + "/item/app/" + app_id + '/',{fields: {'title': 'fgdsfgdsf'}},function(response) {
cb.call(this,response);
});
It returns the following error:
{"error_propagate":false,"error_parameters":{},"error_detail":null,"error_description":"No matching operation could be found. No body was given.","error":"not_found"}
Only "title" attribute is required in the app - I checked that in Podio GUI. I also tried to remove trailing slash from the url where I post to, then a similar error occurs, but with the URL not found message in the error description.
I'm going to setup a proxy to catch a raw request, but maybe someone just sees the error in the code?
Any help is appreciated.
Nevermind on this, I found a solution. The thing is that addItem call was my first "real"-API method implementation with JSON parameters in the body. The former calls were authentication and getApp which is GET and doesn't have any parameters.
The problem is that Podio supports POST key-value pairs for authentication, but doesn't support this for all the calls, and I was trying to utilize single _makeRequest() method for all the calls, both auth and real-API ones.
Looks like I need to implement one for auth and one for all API calls.
Anyway, if someone needs a working proof of concept for addItem call on node, here it is (assuming you've got an auth token beforehand)
_request({method: 'POST', url: "https://api.podio.com/item/app/" + app_id + '/', headers: headers, body: JSON.stringify({fields: {'title': 'gdfgdsfgds'}})},function(error, response, body) {
console.log(body);
});
You should set content-type to application/json
send the body as stringfied json.
const getHeaders = async () => {
const headers = {
Accept: 'application/json',
'Content-Type': 'application/json; charset=utf-8',
};
const token = "YOUR APP TOKEN HERE";
headers.Authorization = `Bearer ${token}`;
return headers;
}
const createItem = async (data) => {
const uri = `https://api.podio.com/item/app/${APP_ID}/`;
const payload = {
fields: {
[data.FIELD_ID]: [data.FIELD_VALUE],
},
};
const response = await fetch(uri, {
method: 'POST',
headers: await getHeaders(),
body: JSON.stringify(payload),
});
const newItem = await response.json();
return newItem;
}

Resources