I'm trying to send a GET request that requires some authorization, however it seems Angular is not keen on sending the required header as well. At least it's not showing up on the network tab in IE.
My code is like this:
var authString = 'NTLM ' + this.base64Encode('username' + ':' + 'passowrd');
$http.get('link/to/api', { headers: { Authorization: authString } })
Am I missing something, or just doing it wrong?
Related
I'm writing a full stack app. I have a python backend using flask that sends a file and a Vue client that receives. Its been working fine up until the point when I try to send the filename over using a Content-Disposition header.
On the backend I've tried:
return send_file(base_path + filename, as_attachment=True, download_name=filename)
And to set the headers manually,
response = make_response(send_file(base_path + filename))
response.headers['Content-Disposition'] = f"attachment; filename=\"{filename}\""
return response
I've also tried to put in headers that would not be blocked by CORS just to see if the request would receive the header but to no avail,
response = make_response(send_file(base_path + filename))
response.headers['Content-Type'] = "sample/info"
return response
I'm printing the header to the console by doing
fetch('http://localhost:4999/rdownload/' + this.$route.params.id, {
method: 'GET'
}).then(res =\> {
if (res.status == '500') { }
console.log(res.headers)
//const header = res.headers.get('Content-Disposition');
//console.log(header)
res.blob().then((blob) => {
/* ... */
})
})
Any help would be appreciated! Thanks :)
Research
In the interest of logging the solution I found and helping out anyone in the future who may be interested in knowing the answer here's what I discovered:
There is a restriction to access response headers when you are using Fetch API over CORS.
https://stackoverflow.com/a/44816592/20342081
So, no matter what using the JS fetch-api you will be unable to access all headers (outside of Cache-Control, Content-Language, Content-Type, Expires, Last-Modified, and Pragma) unless you expose them by specifying them in a request header. That would look something like this:
fetch('https://myrequest/requestend/', {
headers: {
'Access-Control-Expose-Headers': 'Content-Disposition'
}
})
When a cross-origin source accesses your API you will have to expose the header from the back end as well. https://stackoverflow.com/a/66291644/20342081
I was also confused about how the differences between Access-Control-Expose-Headers and Access-Control-Allow-Headers. In my case the solution was use "expose headers" on both the frontend and the backend (and allow wouldn't work). However, Allow has its own applications which I have yet to understand fully. For those endeavoring check out: https://stackoverflow.com/a/28108431/20342081
Solution
I implemented these things in my code by doing:
class RequestResult(Resource):
def get(self, index):
base_path = f"Requests/{index}/"
filename = os.listdir(base_path)[0]
response = make_response(send_file(base_path + filename, as_attachment=True, download_name=filename))
response.headers['Access-Control-Expose-Headers'] = "Content-Disposition"
return response
And on the front end exposing the header as well on the fetch request:
fetch('http://localhost:4999/rdownload/' + this.$route.params.id, {
method: 'GET',
mode: 'cors',
headers: {
'Access-Control-Expose-Headers': 'Content-Disposition'
}
})
I hope this is helpful for the next 5 people who open this in the next 10 years!
I've a problem with the OAuth for the authentication to the API of Meteomatics.
The think I'm trying to do is to get the data from the API of Meteomatics (I've a Basic account). The API respond to me that I've to authenticate but when I set the header for get the token it gave me an error.
The documentation says that I've to put the script below:
var username = '<my_username>';
var password = '<my_password>';
let headers = new Headers();
headers.set('Authorization', 'Basic' + btoa(username + ":" + password));
fetch('https://login.meteomatics.com/api/v1/token', {
//mode: 'no-cors',
method: 'GET',
headers: headers
}).then(function (resp) {
return resp.json();
}).then(function (data) {
var token = data.access_token;
console.log('token', token);
}).catch(function (err) {
console.log('something went wrong', err);
});
The console give me this error:
image of error.
I've read something about CORS, but I don't understand what is the problem. Am I missing something ?
Thanks in advance for those who reply.
Summary of the discussion to the question
It seems that the token endpoint https://login.meteomatics.com/api/v1/token does not support CORS but the API endpoints do, see for example
> curl -I -X OPTIONS -H "Origin:http://localhost" "https://api.meteomatics.com/2022-05-17T00:00:00ZP1D:PT1H/t_2m:C,relative_humidity_2m:p/47.4245,9.3767/html?model=mix&request_type=GET"
Access-Control-Allow-Origin: http://localhost
Access-Control-Allow-Credentials: true
Access-Control-Allow-Methods: GET,POST,OPTIONS
Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept, Authorization
While trying to make the token request from the browser, you handle username and password in client-side Javascript:
headers.set('Authorization', 'Basic' + btoa(username + ":" + password));
You could as well use client-side Javascript to manufacture a request that prefixes the hostname with username and password:
fetch('https://' + username + ':' + password + '#api.meteomatics.com/...')
Meteomatics would accept this method of authentication, while supporting CORS.
A cleaner solution, however, would be to store the username and password on your server and have your server make the token request to https://login.meteomatics.com/api/v1/token. In this case, visitors of your web page would to authenticate to your server, not to meteomatics.com, which for them is a third party.
I have http patch request with Bearer Token Authorization. But the Http Request get a Unauthorized error from the Server, when making the exact same Request(console.log(url + token) and then copy it from the console) in Postman, it works.
What could be the Problem ?
this.getToken().subscribe((data: FormData) => {
const httpOptions = {
headers: new HttpHeaders({
'Authorization': ('Bearer ' + data['access_token'])
})
}
console.log("URL with " + httpOptions.headers.get("Authorization"));
this.http.patch("URL",httpOptions).subscribe((articledata: Article)=>
{
console.log(articledata);
})
});
So this should work, since copying the output and using it in Postman works, but i get a 401 Unauthorized.
For Anyone that needs it, i used http.patch wrong, the headers are the 3rd parameter after url and body.
I am trying to make an api call in Javascript. I am fetching a URL and passing in options, as shown in the image. I am unable to access the API, because I believe I am not passing in my client ID and client secret properly. I also have a redirect URI, but I am unsure of how to specify these in my options and what the syntax is.
Does anyone have any advice on how I can specify this information? Also, is using btoa to convert it to base64 incorrect?
My options I am passing in to my fetch request:
const options = {
method: 'GET',
json: true,
agent: agent,
headers: {
Authorization: 'Basic ' + btoa(client_id + ':' + client_secret),
redirect_uri: `{URI HERE}
}
}
My options I am passing in to my fetch request
Thank you
How can I send authorization credentials using fetch?
It worked using postman but on Chrome I keep receiving this message:
Request cannot be constructed from a URL that includes credentials
You can't define user:pass#host in the URL. Just set the Authorization http Header:
var headers = new Headers();
headers.append('Authorization', 'Basic ' + btoa(username + ':' + password));
fetch('https://host.com', {headers: headers})
Maybe you can use some extension like Modify Headers and include in it your credentials data like you are including un postman.