As the title says, I got a 400 Bad Request error when I tried to get the code exchanged for an access token against https://app.asana.com/-/oauth_token.
I honestly can’t think of what could be causing this. I will post the code and would appreciate anyone’s help.
const GetAsanaAccessToken = async (req, res) => {
const body = {
grant_type: 'authorization_code',
client_id: process.env.NEXT_PUBLIC_ASANA_CLIENT_ID,
client_secret: process.env.ASANA_CLIENT_SECRET,
redirect_uri: process.env.NEXT_PUBLIC_ASANA_REDIRECT_URI,
code: req.body.code // The code obtained in the previous flow goes here.
};
console.log({ body });
const url = 'https://app.asana.com/-/oauth_token';
const response = await fetch(url, {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/x-www-form-urlencoded'
},
body: JSON.stringify(body)
})
.then((res) => {
console.log({ res });
return res.json();
})
.catch((err) => {
console.log({ err });
return err;
});
res.status(200).json(response);
};
export default GetAsanaAccessToken; Then { res } will be like this
{
res: Response {
size: 0,
timeout: 0,
[Symbol(Body internals)]: { body: [PassThrough], disturbed: false, error: null },
[Symbol(Response internals)]: {
url: 'https://app.asana.com/-/oauth_token',
status: 400,
statusText: 'Bad Request',
headers: [Headers],
counter: 0
}
}
}
I have asked the same question in the Asana forum, but since it is often unresolved, I have posted it here as well.
This is the cause.
body: JSON.stringify(body)
Replaced above with below, then worked.
body: Object.keys(body)
.map((key) => `${key}=${encodeURIComponent(body[key])}`)
.join('&');
Because the original one resulted in
{"grant_type":"authorization_code","client_id":"xxx","client_secret":"xxx","redirect_uri":"http://localhost:3000/","code":"xxx"}
It worked when I made it look like the one below (I just made it by hand, so it really encodes slashes, etc.) instead of the one above.
grant_type=authorization_code&client_id=xxx&client_secret=xxx&redirect_uri=http://localhost:3000/&code=xxx