Request succeeds with `request` but fails with `axios` - node.js

I have this microsoft graph authentication code, making what I think is the same request using axios and then using request. However, the axios request fails with 404, whereas the request request succeeds. What am I doing wrong with axios?
const axios = require('axios')
const request = require("request");
const FormData = require('form-data');
const data = FormData()
data.append('client_id', XXXXXXXXXXX),
data.append('client_secret', XXXXXXXXX),
data.append('scope', "https://graph.microsoft.com/.default"),
data.append('grant_type', 'client_credentials')
const requestParams = {
client_id: logins.activedirectory.clientID,
client_secret: logins.activedirectory.clientSecret,
scope: "https://graph.microsoft.com/.default",
grant_type: "client_credentials",
};
const endpoint = "https://login.microsoftonline.com/" + XXXXXXXX + "/oauth2/v2.0/token";
///////// AXIOS //////////
axios({
method: 'post',
url: endpoint,
data: data,
headers: {'Content-Type': 'application/x-www-form-urlencoded' }
})
.then(function (response) {
console.log(response);
})
.catch(function (response) {
console.log(response);
});
///////// REQUEST /////////
request.post({ url:endpoint, form: requestParams }, function (err, response, body) {
if (err) {
console.log(err);
} else {
console.log(body);
}
});

Related

'Missing or duplicate parameters' in Access Token Response

I'm trying to fetch the OAuth access token with the lambda function but getting fhe following error:
data: {
error: 'invalid_request',
error_description: 'Missing or duplicate parameters'
}
This is the code:
var axios = require("axios").default;
exports.handler = async (event) => {
var options = {
method: 'POST',
url: 'https://******/auth/oauth/v2/token',
headers: {'content-type': 'application/x-www-form-urlencoded'},
data: {
grant_type: 'client_credentials',
client_id: '*********',
client_secret: '******'
}
};
try {
const resp = await axios.request(options);
console.log(resp.data)
} catch (err){
console.error(err);
}
};
When I try to run the request with the Postman it returns the valid token.
As stated by #derpirscher, I had to properly serialize the data object using 'qs' library. After that I was able to fetch the access token successfully.
var axios = require("axios").default;
const qs = require('qs');
exports.handler = async (event) => {
var data = {
grant_type: 'client_credentials',
client_id: '*********',
client_secret: '************'
};
var options = {
method: 'POST',
url: 'https://************/auth/oauth/v2/token',
headers: {'content-type': 'application/x-www-form-urlencoded'},
data: qs.stringify(data)
};
try {
const resp = await axios.request(options);
console.log(resp.data)
} catch (err){
console.error(err);
}
};

Axios FormAppend post method and node.js

I trigger / upload in node.js by calling the submit function inside a class. But in Node.js, req.body is empty. In fact, I append data to FormData in the submit function and send it to node.js. Where am I doing the problem?
Class
submit(){
const data = new FormData()
data.append('file', this.state.selectedFile)
data.append('ID', uniqid())
let url = "http://localhost:5000/upload";
axios({
method: "POST",
url: url,
data: data,
headers: {
"Content-Type": "application/json"
}
}).then(res => {
});
}
Node.js
app.post('/upload', (req, res) => {
axios.post('https://....php', req.body, {
}).then(function (response) {
}).catch(function (error) {
console.log('errorserver', error);
});
});
Try to put file after text like this.
submit(){
const data = new FormData()
data.append('ID', uniqid())
data.append('file', this.state.selectedFile)
let url = "http://localhost:5000/upload";
axios({
method: "POST",
url: url,
data: data,
headers: {
"Content-Type": "application/json"
}
}).then(res => {
});
}

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.

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 do you make this curl request in node

This curl request to the spotify API works perfectly fine
curl -X "POST" -H "Authorization: Basic <my-key-here>" -d grant_type=client_credentials https://accounts.spotify.com/api/token
I'm trying to do this in node, but it's not working and returns a 400 Bad Request. Here is my code. What am I doing wrong?
function AuthRequest(key) {
const req_body_params = JSON.stringify({
grant_type: "client_credentials"
})
const base64_enc = new Buffer(key).toString("base64")
const options = {
host: "accounts.spotify.com",
port: 443,
path: "api/token",
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": `Basic ${base64_enc}`
}
}
const req = https.request(options, function (res) {
res.on('data', function (data) {
alert("success: " + data)
})
})
req.on('error', function (err) {
alert("error: " + err)
})
req.write(req_body_params)
req.end()
}
I'm trying to use the Client Credentials method as explained here: https://developer.spotify.com/web-api/authorization-guide/
The request should be in application/x-www-form-urlencoded instead of JSON, it should be const req_body_params = "grant_type=client_credentials" with a header of "Content-Type": "application/x-www-form-urlencoded"
function AuthRequest(key) {
const req_body_params = "grant_type=client_credentials";
const base64_enc = new Buffer(key).toString("base64");
const options = {
host: "accounts.spotify.com",
port: 443,
path: "/api/token",
method: "POST",
headers: {
"Content-Type": "application/x-www-form-urlencoded",
"Authorization": `Basic ${base64_enc}`
}
};
const req = https.request(options, function(res) {
res.on('data', function(data) {
alert("success: " + data)
})
});
req.on('error', function(err) {
alert("error: " + err)
});
req.write(req_body_params);
req.end();
}
Because token expires is good to request them dynamically, I created a method that output a token as a promise, then you can consume in your request.
const axios = require('axios')
const client_id = process.env.SPOTIFY_CLIENT_ID;
const client_secret = process.env.SPOTIFY_CLIENT_SECRET;
function getToken( ) {
return axios({
url: 'https://accounts.spotify.com/api/token',
method: 'post',
params: {
grant_type: 'client_credentials'
},
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
auth: {
username: client_id,
password: client_secret
}
})
}
async function getSpotifyData( endpoint ){
const tokenData = await getToken( );
const token = tokenData.data.access_token;
axios({
url: `https://api.spotify.com/v1/${endpoint}`,
method: 'get',
headers: {
'Authorization': 'Bearer ' + token
}
}).then( response => {
console.log( response.data );
return response.data;
}).catch( error => {
throw new Error(error);
});
}
getSpotifyData( 'browse/new-releases' );

Resources