-1

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.

Andrew
  • 3
  • 1
  • 3
  • It seems the API does not allow cross-origin AJAX requests. It's likely if you want to access it via AJAX you'll actually need to send an AJAX request to _your_ server, and then have some server-side code which makes the HTTP request to the API, and returns the result back to the AJAX call, which in turn shows it on the page. This is sometimes known as an "API proxy". If you don't know much about CORS, what it does or why it exits, then https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS is an ideal starting point. – ADyson May 17 '22 at 12:41
  • Your other option is to speak to the company which provides the API via their support channel and ask if they do in fact support CORS and whether there's a way to register your website (and also your localhost, for testing purposes) as a valid CORS origin in their API. Some API vendors offer this, but from a brief glance at their documentation I didn't see any mention of it. – ADyson May 17 '22 at 12:42
  • P.S. https://stackoverflow.com/questions/59595110/api-javascript-will-not-return-result seems to be asking about the same issue for this API, and comes to the same conclusion as I've done in my first comment. Arguably, your question is a direct duplicate of that one. – ADyson May 17 '22 at 12:43
  • https://www.meteomatics.com/en/api/request/ mentions that can also prefix the hostname with your username and password, as in `https://username:password@api.meteomatics.com`, have you tried that? – Heiko Theißen May 17 '22 at 15:32
  • @HeikoTheißen Yes, I've tried but it doesn't work anyway. – Andrew May 17 '22 at 15:53
  • @HeikoTheißen that isn't going to solve a CORS issue. – ADyson May 17 '22 at 15:54
  • I thought that meteomatics endpoints other than the `/token` endpoint _do_ support CORS. Try `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"` – Heiko Theißen May 17 '22 at 16:01
  • @HeikoTheißen well that's useful in theory, but if you can't get a token in the first place... – ADyson May 17 '22 at 16:04
  • You don't need a token if you use the `https://username:password@api.meteomatics.com` syntax. – Heiko Theißen May 17 '22 at 16:05
  • @HeikoTheißen Perhaps but I really wouldn't recommend putting that in any browser-based code, cos then you basically gave all your users your API credentials... TBF the OP's original code suffers from the same issue too though – ADyson May 17 '22 at 16:07
  • `headers.set('Authorization', 'Basic' + btoa(username + ":" + password))` is also browser-based code. What's the advantage over `https://username:password@api.meteomatics.com`? – Heiko Theißen May 17 '22 at 16:08
  • @HeikoTheißen I edited my previous comment with that exact point already before you replied - please refresh. – ADyson May 17 '22 at 16:14

1 Answers1

0

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.

Heiko Theißen
  • 12,807
  • 2
  • 7
  • 31