Axios 400 Bad Request Cognito JWT generation in Node Js - node.js

I am trying to create Cognito JWtoken via POST call with axios in Lambda function using node js , but i am getting error 400 bad request.
In parallel it is working fine in Postman.
Code :
await axios.post('https://smartfactoryfabric-dev.auth.us-east-1.amazoncognito.com/oauth2/token', {
grant_type: grantType, // This is the body part
redirect_uri: redirectURI,
client_id: clientid,
code: 'fb06a2dd-XXXXXXXXX-f186c6302806'
}, {
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Authorization': 'Basic ' + authValue
}
})
.then(response => {
console.log(response)
})
.catch(error => {
console.log(error.response)
});

You need to URL encode the body of your request into a single string. You can use querystring.stringify to do this.
let data = querystring.stringify({
grant_type: 'grantType',
redirect_uri: 'redirectURI',
client_id: 'clientid',
code: 'fb06a2dd-XXXXXXXXX-f186c6302806'
})
=> 'client_id=clientid&code=fb06a2dd-XXXXXXXXX-f186c6302806&grant_type=grantType&redirect_uri=redirectURI'
Then your request will look like this:
await axios.post('https://smartfactoryfabric-dev.auth.us-east-1.amazoncognito.com/oauth2/token',
data,
{
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Authorization': 'Basic ' + authValue
}
})

Related

400 Error when requesting a token from Discord API

I'm trying to create a login process with Discord's API. Per the documentation I'm suppose to use the code returned on the callback URL to make another call to receive the access token. I've followed the instructions here. However, I keep receiving a 400 error when making the call.
Any help on what I need to correct?
let options = {
method: 'POST',
headers: {
'Authorization': 'Basic ' + discordInfo.client_id + ":" + discordInfo.client_secret,
'Content-Type': 'application/x-www-form-urlencoded'
},
data: {
'client_id': discordInfo.client_id,
'client_secret': discordInfo.client_secret,
'grant_type': 'authorization_code',
'code': req.query.code,
'redirect_uri': discordInfo.callbackUrl,
'scope': 'identify email'
}
}
let discord_data = await fetch('https://discord.com/api/oauth2/token', options).then((response) => {
if (response.status >= 400) {
throw new Error("Bad response from server");
}
return response.json();
}).then((response) => {
console.log('Discord Response', response);
}).catch((error) => {
console.log(error);
});
After further research, I discovered the following video which helped me out.
Here is the working code:
let options = {
url: 'https://discord.com/api/oauth2/token',
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
body: new URLSearchParams({
'client_id': discordInfo.client_id,
'client_secret': discordInfo.client_secret,
'grant_type': 'client_credentials',
'code': req.query.code,
'redirect_uri': discordInfo.callbackUrl,
'scope': 'identify email'
})
}
let discord_data = await fetch('https://discord.com/api/oauth2/token', options).then((response) => {
return response.json();
}).then((response) => {
return response;
});

Converting Curl to Nodejs Axios - Obtaining an Access Token

I am currently using curl in order to obtain an access token so I can consume an api with said token. The curl command I use is as follows:
curl --user <client_id>:<client_secret> https://api.ed-fi.org/v3/api/oauth/token --data 'grant_type=client_credentials'
It works and all...but instead of curling I want to utilize the axios library to get this access token instead.
Here's what I have but it doesn't work.
const buff = new Buffer.from('<client_id>:<client_secret>';
const base64data = buff.toString('base64');
axios({
method: 'POST',
url: 'https://api.ed-fi.org/v3/api/oauth/token',
headers: {
Authorization: `Basic ${base64data}`
},
data: { 'grant_type': 'client_credentials' }
})
.then(response => {
console.log(response);
})
.catch(error => {
console.log(error);
});
I can't figure out what I'm missing or doing wrong?
You should change Content-Type (default for axios is JSON) and pass body just like you did in case of curl:
axios({
method: 'POST',
url: 'https://api.ed-fi.org/v3/api/oauth/token',
headers: {
Authorization: `Basic ${base64data}`,
'Content-Type': 'application/x-www-form-urlencoded'
},
data: 'grant_type=client_credentials'
})
.then(response => {
console.log(response);
})
.catch(error => {
console.log(error);
});

Try to fetch Instagram access token with all required params but still get an error code 400

This is the server side code that tried to make a POST request to Instagram to get an access token
app.get('/instagram/json', (req, res) => {
axios({
method: 'post',
url: 'https://api.instagram.com/oauth/access_token',
data: {
'client_id': instagramClientId,
'client_secret': instagramClientSecret,
'grant_type': 'authorization_code',
'redirect_uri': 'http://localhost:3000',
'code': instagramCode
}
}).then((response) => {
console.log(response);
}).catch((e) => {
console.log(e);
});
});
This is the error response I get. It tells me that "client_id" is required despite I clearly have provided it.
data:
{ error_type: 'OAuthException',
code: 400,
error_message: 'You must provide a client_id' } } }
Here is a solution:
const insta_form = new URLSearchParams();
insta_form.append('client_id', 'xxx');
insta_form.append('client_secret', 'xxx');
insta_form.append('grant_type', 'authorization_code');
insta_form.append('redirect_uri', 'xxx');
insta_form.append(
'code',
'xxx'
);
await axios({
method: 'POST',
url: 'https://api.instagram.com/oauth/access_token',
data: insta_form,
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
})
.then((response) => {
console.log(response);
})
.catch((err) => {
console.log(err.response);
});
}
import axios from 'axios'
import {stringify} from 'qs'
const response = await axios({
method: "post",
url: "https://api.instagram.com/oauth/access_token",
data: stringify({
client_id: CLIENT_ID,
client_secret: CLIENT_SECRET,
grant_type: 'authorization_code',
redirect_uri: REDIRECT_URL,
code
}),
headers: { "Content-Type": 'application/x-www-form-urlencoded' },
})
Late, but since there's not a good answer on the web and took me a while:
You'd have to wrap your body inside a form-data before providing it to fetch-node's post.
Install form-data: npm install --save form-data
then:
const formData = require("form-data");
const insta_form = new formData();
insta_form.append("client_id", your client id);
insta_form.append("client_secret", your client secret);
insta_form.append("grant_type", "authorization_code");
insta_form.append("redirect_uri", your redirect uri);
insta_form.append("code", user code);
const shortTokenRes = await fetch(
"https://api.instagram.com/oauth/access_token",
{
method: "POST",
body: insta_form,
}
);

How to use bearer token for authorization for POST method in sync-request?

How can we use bearer token with POST method using npm sync-request? The sync-request resource page has the way to use authorization in GET request but not in POST request.
*******GET Request*******
var request = require('sync-request');
var res = request('GET', 'https://example.com', {
'headers': {
'user-agent': 'example-user-agent'
}
});
****POST Request*****
var request = require('sync-request');
var res = request('POST', 'https://example.com/create-user', {
json: { username: 'Name' }
});
Not sure why you would want to use sync-request which can cause timing issues but this should work with either sync-request or request
// *******GET Request*******
var request = require('sync-request');
var res = request('GET', 'https://example.com', {
'headers': {
'user-agent': 'example-user-agent',
'authorization', 'Bearer ' + authId
}
});
// ****POST Request*****
var request = require('sync-request');
var res = request('POST', 'https://example.com/create-user', {
'headers': {
'authorization', 'Bearer ' + authId
},
json: { username: 'Name' }
});
authId needs to be whatever your bearer token spoils be for your app.
I would suggest use of axis and example below:-
GET
import axios from "axios";
axios({
method: 'get',
url: url,
headers: {
'Content-Type': 'application/json'
}
}).then(function (response) {
console.log(response);
}).catch((err) => {
console.log(err)
));
POST
axios({
method: 'post',
url: url,
data: JSON.stringify({orders}),
headers: {
'Content-Type': 'application/json',
'Authorization': userObj.token
}
}).then(function (response) {
console.log(response)
});
Where ubserObj.token -
Bearer Token ex: Bearer ASDF#!##!ADFASDF!##!##
This will be on the server side settings.

How to retrieve PayPal REST Api access-token using node

How to get the PayPal access-token needed to leverage the REST Api by using node?
Once you have a PayPal client Id and a Client Secret you can use the following:
var request = require('request');
request.post({
uri: "https://api.sandbox.paypal.com/v1/oauth2/token",
headers: {
"Accept": "application/json",
"Accept-Language": "en_US",
"content-type": "application/x-www-form-urlencoded"
},
auth: {
'user': '---your cliend ID---',
'pass': '---your client secret---',
// 'sendImmediately': false
},
form: {
"grant_type": "client_credentials"
}
}, function(error, response, body) {
console.log(body);
});
The response, if successful, will be something as the following:
{
"scope":"https://api.paypal.com/v1/payments/.* ---and more URL callable with the access-token---",
"access_token":"---your access-token---",
"token_type":"Bearer",
"app_id":"APP-1234567890",
"expires_in":28800
}
Also, you can use axios, and async/await:
const axios = require('axios');
(async () => {
try {
const { data: { access_token } } = await axios({
url: 'https://api.sandbox.paypal.com/v1/oauth2/token',
method: 'post',
headers: {
Accept: 'application/json',
'Accept-Language': 'en_US',
'content-type': 'application/x-www-form-urlencoded',
},
auth: {
username: client_id,
password: client_secret,
},
params: {
grant_type: 'client_credentials',
},
});
console.log('access_token: ', access_token);
} catch (e) {
console.error(e);
}
})();
Modern problems require modern solutions:
const fetch = require('node-fetch');
const authUrl = "https://api-m.sandbox.paypal.com/v1/oauth2/token";
const clientIdAndSecret = "CLIENT_ID:SECRET_CODE";
const base64 = Buffer.from(clientIdAndSecret).toString('base64')
fetch(authUrl, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json',
'Accept-Language': 'en_US',
'Authorization': `Basic ${base64}`,
},
body: 'grant_type=client_credentials'
}).then(function(response) {
return response.json();
}).then(function(data) {
console.log(data.access_token);
}).catch(function() {
console.log("couldn't get auth token");
});
You could use PayPal-Node-SDK to make calls to PayPal Rest APIs. It handles all the authorization and authentication for you.
Here is how I get the access_token using superagent
superagent.post('https://api.sandbox.paypal.com/v1/oauth2/token')
.set("Accept","application/json")
.set("Accept-Language","en_US")
.set("content-type","application/x-www-form-urlencoded")
.auth("Your Client Id","Your Secret")
.send({"grant_type": "client_credentials"})
.then((res) => console.log("response",res.body))

Resources