EDIT:
I was reading the documentation wrong. In this world of JSON I didn't notice the request was sending form data. Silly mistake.
It was also the wrong endpoint.
The request should have looked like:
fetch(
'https://api.amazon.com/auth/o2/token/',
{
method: 'POST',
headers:{
'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'
},
body:
`?redirect_uri=${redirectUri}` +
`&code=${clientCode}` +
`&client_id=${clientId}` +
`&client_secret=${clientSecret}` +
'&grant_type=authorization_code'
}
)
I'm trying to trade a token obtained with the code flow in cognito's login page, but the request responds with a status 400 "malformed request".
The documentation I am following is: https://developer.amazon.com/docs/login-with-amazon/authorization-code-grant.html#access-token-request
I am using the browser to make the following request:
fetch(
'https://api.amazon.com/auth/o2/token/' +
`?redirect_uri=${encodeURIComponent(redirectUri)}` +
`&code=${encodeURIComponent(clientCode)}` +
`&client_id=${encodeURIComponent(clientId)}` +
`&client_secret=${encodeURIComponent(clientSecret)}` +
'&grant_type=authorization_code',
{
method: 'POST',
headers:{
'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'
}
}
)
Which results in the client sending the following request:
POST
https://api.amazon.com/auth/o2/token/?redirect_uri=http%3A%2F%2Flocalhost%3A3000%2Floggedin&code=<code>&client_id=<client_id>o&client_secret=<client_secret>&grant_type=authorization_code
The response:
{
"error_description": "Malformed request",
"error":"invalid_request"
}
Related
I'm trying to use the fetch API in vanilla JavaScript to generate a token provided by Django OAuth Toolkit. The application I've created in DOT uses the "Resource owner password-based" authorization grant type. My code looks like this (grant_type, username and password are provided through request.formData()):
const data = await request.formData();
const oauth = await fetch(`${API_ROOT}/o/token`, {
method: 'POST',
headers: {
'Content-Type': 'multipart/form-data',
Authorization: `Basic ${Buffer.from(CLIENT_ID + ':' + CLIENT_SECRET).toString('base64')}`
},
body: data
});
This request imitates a successful GET request I've created using Insomnia (with Multipart Form data for grant_type, username and password + CLIENT_ID and CLIENT_SECRET as the username and password in Basic Auth). In other words, I don't understand why the JavaScript fetch request does not work even though it is supposed to be identical to the Insomnia request. The JavaScript fetch request returns a 400 error. When I remove the Content-Type header, I get a 500 error. What am I doing wrong?
EDIT: It may be worth noting that I am making this fetch call within a SvelteKit application.
As it turns out, in this particular case I DID need to set Content-Type. I found this answer: Trying to get access token with django-oauth-toolkit using fetch not working while working using jquery
My code works as follows:
const data = await request.formData();
const oauth = await fetch(`${API_ROOT}/oauth/token/`, {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
},
Authorization: `Basic ${Buffer.from(CLIENT_ID + ':' + CLIENT_SECRET).toString('base64')}`,
},
body: formDataToUrlEncoded(data)
});
The formDataToUrlEncoded function roughly ressembles the one posted in the above post:
export function formDataToUrlEncoded(formData) {
var url_encoded = '';
for (var pair of formData) {
if (url_encoded != '') {
url_encoded += '&';
}
url_encoded += encodeURIComponent(pair[0]) + '=' + encodeURIComponent(pair[1]);
}
return url_encoded;
}
I am trying to make a call using JavaScript's Fetch API to generate an OAuth Token but I keep receiving a 400 response code and I'm not sure why. I wrote the key and secret to the console to verify their values, and I made the same API call using cURL (with the response I expected). Is there a small issue in my syntax?
fetch('https://api.petfinder.com/v2/oauth2/token', {
method: 'POST',
body: 'grant_type=client_credentials&client_id=' + key + '&client_secret=' + secret
}).then(r => { response = r.json() });
If the request body is a string, the Content-Type header is set to text/plain;charset=UTF-8 by default. Since you're sending urlencoded data, you have to set the Content-Type header to application/x-www-form-urlencoded.
fetch('https://api.petfinder.com/v2/oauth2/token', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: 'grant_type=client_credentials&client_id=' + key + '&client_secret=' + secret
})
As I mentioned in a comment, you shouldn't make the above request from a browser since it exposes the client secret.
Thanks to #Arun's recommendation of adding Content-Type, I am getting the right response now.
Also, for any other JavaScript newbies playing around with the petfinder API, this is the chain that I used to extract the token from the response:
fetch('https://api.petfinder.com/v2/oauth2/token', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: 'grant_type=client_credentials&client_id=' + key + '&client_secret=' + secret
}).then(response => response.json().then(data => ({
data: data,
status: response.status})
).then(function(res) {
console.log(res.status, res.data.access_token);
}));
I'm trying to implement this post request using curl in the JS Fetch API:
curl --user apikey:{my_secret_apikey} --request POST --header "Content-Type: application/json" --data "{\"text\":[\"Hello\"],\"model_id\":\"en-es\"}" "{my_secret_url}/v3/translate?version=2018-05-01"
I'm having trouble implementing the API key.
I tried this, but it doesn't work. I get a 401 unauthorized error back from the server.
fetch(url, {
method: "POST",
headers: { 'Content-Type': 'application/json' },
user: {
"apikey": blablabla_api_key
}
body: {
"text": [term],
"model_id": "en-hi"
}
}).then(res ........
Any help is appreciated!
edit: if you have any other suggestion as to how to implement this post request into JS using some other HTTP library, that helpful too!
Edited code with auth header:
let headers = new Headers();
headers.append('Authorization', 'Basic ' + btoa("apikey" + ":" + "my_api_key"));
headers.append('Content-Type', 'application/json');
fetch(url, {
method: "POST",
headers: headers,
body: {
"text": ["Hello"],
"model_id": "en-es"
}
}).then(result => {
console.log(result);
resolve(result.translations[0].translation);
}).catch(err => console.log(err));
This results in a 400 Bad Request error, even though the curl request works fine.
hopefully, I am not too late with answering your question.
I encountered the same problem as you did and my solution was to encode the authorization into base64.
https://observablehq.com/#mbostock/fetch-with-basic-auth#:~:text=To%20use%20basic%20authentication%20with,result%20in%20a%20401%20error.
I am using Node.js, so I needed to use a Buffer for the encoding process.
If I understood your problem correctly, you'd have to do the following:
let buffer = Buffer.from(apikey:{my_secret_apikey})
let base64data = buff.toString('base64')
Your authorization header should then be set to something like this:
headers: {'Authorization': `Basic ${base64data}`}
This helped me a to solve at least the problem I was struggling with. Hope it works for you as well!
I'm trying to receive a token from the Spotify api to allow me to search the api and such for songs and other information.
On my sever application index.js I start by requiring the package:
var request = require('ajax-request');
Later on I go to request my token:
request.post({
method: 'POST',
url: 'https://accounts.spotify.com/api/token',
'Content-Type' : 'application/x-www-form-urlencoded',
header: {
Authorization: 'Basic' + <urlEncodedClientIdAndClientSecret>,
},
data: {
grant_type: 'client_credentials'
}
}, function(err, res, body) {
});
However if I try and console log this it always returns undefined, is there an issue with how I've laid out my post request or is there something else I'm missing?
Oh....I just looked at your request again....are you missing a space after the "Basic"? Try this:
Authorization: 'Basic ' + <urlEncodedClientIdAndClientSecret>,
I try to get a token from Spotify with Client Credentials Flow. I get in answer status 400 and this error : "invalid_client". I cannot understand where is my mistake.
let oAuthOptions = {
url: 'https://accounts.spotify.com/api/token',
method: 'POST',
headers: {
'Authorization' : 'Basic ' + btoa(CLIENT_ID+':'+CLIENT_SECRET)
},
body: "grant_type=client_credentials",
json : true
};
$.post(oAuthOptions['url'],oAuthOptions,function() {
console.log('get answer');
});
The invalid_client error occurs when you are sending a bad Authorization header (not bad, maybe a bad client_id?)
Recheck your client_id and client_secret (And if they are properly in base64)
It should work.