lichess-org / lila

♞ lichess.org: the forever free, adless and open source chess server ♞
https://lichess.org
GNU Affero General Public License v3.0
15.62k stars 2.28k forks source link

API game download does not work in browser if Authorization header is submitted #4441

Closed typescriptstudies closed 6 years ago

typescriptstudies commented 6 years ago

API game download works fine in browser with Javascript fetch API as far as no Authorization header is submitted. Once there is an Authorization header ( or any header, even "Foo": "Bar" ) is present in the request, this error is reported:

http://imagerepo.bitballoon.com/gamesexportapi.png

The request was made from localhost.

The code that made the request:

https://github.com/humbletest/lgbot/blob/public/static/js/app.js#L2516

( currently an always false condition is used for submitting Authorization header, to avoid error )

niklasf commented 6 years ago

tl;dr: Yes, that's annoying. Currently the best workaround is to not send headers other than the default headers.


I'll try to explain.

What you are seeing is the default behavior for cross site requests, i.e. it applies only in the browser. It would work when sending requests from your own server.

By default, unless specifically whitelisted, only some basic headers are allowed.

Now we could whitelist Authorization, but that would allow mixing Cookie authentication with OAuth, which can be tricky and/or dangerous (accidantely exposing user information in cross site requests) for some endpoints.

To keep things (relatively) clean and secure:

typescriptstudies commented 6 years ago

Will /games/export/user download games faster if I submit the cookie for user?

niklasf commented 6 years ago

Yes, but I am not sure you can do that with the fetch API.

typescriptstudies commented 6 years ago

https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch says:

"To cause browsers to send a request with credentials included, even for a cross-origin call, add credentials: 'include' to the init object you pass to the fetch() method."

fetch('https://example.com', {
  credentials: 'include'  
})

However I think a full solution would be to reproduce the whole API for browser fetch with a different endpoint. So instead of /games/export/... you could call /fetch/games/export/....

niklasf commented 6 years ago

credentials will not work on this endpoint. I agree it might be a good idea to make game exports available under /api, so that we don't have to be content with workarounds.

typescriptstudies commented 6 years ago

Before reading the response to my comment I made an attempt with fetch credentials, and I can confirm that it does not work:

http://imagerepo.bitballoon.com/gamesexportapicreds.png

The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard
'*' when the request's credentials mode is 'include'.

I have a server behind this particular client which made the call, so I could in theory use the server to make the request, but this introduces unnecessary complications, so I'm glad that you are considering a separate endpoint and I'm looking forward to using it.

ornicar commented 6 years ago

Here's the new endpoint https://lichess.org/api#operation/apiGamesUser and the deprecated one at the bottom https://lichess.org/api#operation/gamesExportUsername