API is successful with request but fails with axios - node.js

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.

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);
}
};

Request succeeds with `request` but fails with `axios`

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);
}
});

How to add headers in superagent GET request

Here is a basic code:
const superagent = require('superagent');
superagent.get('https://api.arabam.com/pp/step')
.query({ apikey: '_V85Kref7xGZHc1XRpUmOhDDd07zhZTOvUSIbJe_sSNHSDV79EjODA==' })
.end((err, res) => {
if (err) { return console.log(err); }
console.log(res.body.url);
console.log(res.body.explanation);
});
But apikey is header rather than query. How do I send it as a header?
Edit:
I have tried using request module and it simply says that I'm unable to access it
var request = require("request");
request({
uri: "https://api.arabam.com/pp/step",
method: "GET",
'Content-Type' : "application/json",
apikey: "_V85Kref7xGZHc1XRpUmOhDDd07zhZTOvUSIbJe_sSNHSDV79EjODA=="
}, function(error, response, body) {
console.log(body);
});
It says unauthorized to access
From the Setting header fields doc, you should use
request.set('apikey', '_V85Kref7xGZHc1XRpUmOhDDd07zhZTOvUSIbJe_sSNHSDV79EjODA==')
to set the header field.

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,
}
);

oAuth code exchange for secret token

I'm making an app that is supposed to use oAuth to authenticate players from the Blizzard servers, I want to access their character info.. and I can't figure out how to ask for the secret_token. I guess I'm doing my post request wrong below is the code I'm using
app.post('/', function(req, res) {
var code = req.body.code; //this is the code i get ounce the player is redirected back to my redirect_uri
var redirectUri = "https://localhost:3000/oauth_callback.html";
var scope = "wow.profile";
var key = "they client_id i was given";
var secret = "they secret I was given";
var grantType = "authorization_code";
var tokenUri = "https://us.battle.net/oauth/token";
var uriBody = "?client_id=" + key + "&client_secret=" + secret + "&grant_type=authorization_code&code=" + code + "&redirect_uri=" + redirectUri + "&scope=" + scope;
request({
url: tokenUri, //URL to hit
method: 'POST',
headers: {
'Content-Type': "application/x-www-form-urlencoded",
},
body: uriBody //Set the body as a string
}, function(error, response, body){
if(error) {
console.log(error);
} else {
console.log(response.statusCode, body);
}
});
so basically I'm getting the code making a post request to my server with it, and then triggering a post request to the blizzard server trying to exchange my code for an access token.
The error I get is:
401 '{"error":"unauthorized","error_description":"An Authentication object was not found in the SecurityContext"}'
I'm using Node.js & request.js to make the post, my guess is I'm not making a proper request post request?
I think body key is not acceptable in request.
Send data in json if content-type is JSON or form if content-type is x-www-form-urlencoded
Like this
request({
url: tokenUri, //URL to hit
method: 'POST',
headers: {
'Content-Type': "application/x-www-form-urlencoded",
},
form: uriBody //Set the body as a string
}, function(error, response, body){
if(error) {
console.log(error);
} else {
console.log(response.statusCode, body);
}
});
finally! here is how I got it to work!
qs = query-string.js library...
var token_params = qs.stringify({
client_id: key,
client_secret: secret,
code: code,
scope: scope,
grant_type: 'authorization_code',
redirect_uri: redirectUri
});
request('https://us.battle.net/oauth/token?' + token_params, function(error, response, body){
if (error) {
console.log(error);
} else {
console.log(body)
}
});

Resources