arp242 / goatcounter

Easy web analytics. No tracking of personal data.
https://www.goatcounter.com
Other
4.49k stars 184 forks source link

API call with Browser JavaScript fetch() always 403 - Access Forbidden #593

Open Danny-Engelman opened 2 years ago

Danny-Engelman commented 2 years ago

Can't find anything related in the Issues.

I only get 403 - Access Forbidden using this code with generated Token

API documentation spells: bearer and Bearer, but that doesn't make a difference

var site =' ... ';
var token ='bnva3935u6tn36s8b08fh2zflmeofamnsjlj9lqjg8vad4e5';

fetch(`https://${site}.goatcounter.com/api/v0/export`, {
    method: 'POST',
    mode: 'no-cors',
    headers: {
        'Content-Type': 'application/json',
        'Authorization': `Bearer ${token}`
    },
    // body:JSON.stringify({}) // results in 415
}).then(res=>{
    if (res.ok) return res.json();
    else console.warn(res);
}).then(json=>console.log(json));

What am I missing?

Dank je wel, Danny

arp242 commented 2 years ago

API documentation spells: bearer and Bearer, but that doesn't make a difference

This should be Bearer with a capital; I'll fix the typo.

Running your code, it looks like it doesn't actually send the Authorization or Content-Type headers. I have the same (in Firefox).

I tried a whole bunch of different things, and eventually I figured out the mode: 'no-cors' in there is the problem; if I remove that it works (from goatcounter.goatcounter.com):

var site  = 'goatcounter',
    token = 'xxx'

fetch(`https://${site}.goatcounter.com/api/v0/export`, {
    method:  'POST',
    headers: {
        'content-type': 'application/json',
        'Authorization': `Bearer ${token}`
    },
    // body:JSON.stringify({}) // results in 415
}).then(res => {
    if (res.ok)
        return res.json();
    else
        console.warn(res);
}).then(json => console.log(json))

This fetch API is such a ... ugh. If you get something wrong it will just silently do the wrong thing instead of giving you an error.

Either way, it seems everything is okay on the GoatCounter end (aside from the typo in the docs), so I think this can be closed.

Danny-Engelman commented 2 years ago

Alas, I copied your code, and set my sitename and token (let me know a private email address and I can send them)

Chromium:

Firefox:

arp242 commented 2 years ago

Oh right, I just tried it from the GoatCounter page itself, rather than another site. Need to add Access-Control-Allow-Origin: * (or the site name) to the API header to allow it.

What's your use case for calling the API like that? Are you planning to run a script on your website which accesses the API? Because then the token will be public, and if you get the permissions wrong people can adjust settings and whatnot.

Danny-Engelman commented 2 years ago

Yes, I won't be using the token on a public site.

I have a dashboard for our sites, would also like to monitor site traffic

Noot: By Roads Technology werk ik met mensen met een afstand tot de arbeidsmarkt. Mijn team kan hetzelfde als andere IT bedrijven; we doen er alleen wat langer over.

tnx,

Danny

arp242 commented 2 years ago

I'm adding an "Allow embedding from sites" option for #587, to allow people to embed GoatCounter in a frame. I'll also make sure that it'll work for this use case too.

Actually, the frame might be useful for your case too.

Danny-Engelman commented 2 years ago

Dunno if it is your latest API changes, I now get other errors:

cfjedimaster commented 1 year ago

Just chiming in that I'd like CORS enabled for the APIs as well. With the ability to make keys that are read only, this would be safe to use in public sites.

Danny-Engelman commented 1 year ago

I never got it to work...