audiosilo icon indicating copy to clipboard operation
audiosilo copied to clipboard

Playback is not working due to 401 error

Open izderadicka opened this issue 3 years ago • 27 comments

Hi Chris, I've updated demo site https://audioserve.zderadicka.eu (shared secret is mypass) with latest development version of audioserve (from branch position-db).
Connects fine, can browse collection, however cannot play files - due to 401 error - request for audio file (and related image) does not contain Authorization header -

image

izderadicka avatar Sep 26 '21 10:09 izderadicka

Forgot to mention - was using hosted version - https://audioserve.coderior.com/ - is it up to date?

izderadicka avatar Sep 26 '21 10:09 izderadicka

Hi Ivan, I'm just heading out to a wedding, but I'll take a look when I get back. My guess is it's because I'm just passing the url that's returned from the api directly to the audio context, so the Authorization header won't be attached to that.

KodeStar avatar Sep 26 '21 11:09 KodeStar

Ok, I think there are 3 options for this.

  1. The server allows the token to be sent as part of the url so ?trans=m&token=whateverthetokenis
  2. I do a fetch request on the url, download the entire file first then glob it and do a URL.createObjectURL(glob)
  3. I do a fetch request on the url and work out how to stream the chunks

I'll look more into it though. My test server doesn't have a password because it's on the LAN so I didn't need it, so hadn't come across this yet.

KodeStar avatar Sep 26 '21 18:09 KodeStar

If you control the fetch then I guess you can add Authorization header?
What about using Service Workers to intercept fetch - this is what they are designed for - caching and network requests modification. Current web client is using cookies, which work automatically for audio element, even for other origin. Re: Option 1. - Could be done, but having authentication in header is preferred.

izderadicka avatar Sep 27 '21 06:09 izderadicka

It’s not fetch request, it’s currently just setting the audio src to the path returned by the api. Interceptors would work if I was using fetch, and I might try implementing them anyway as I’m doing a lot of fetch requests for things like the description and cover.

Using cookies would be good, unfortunately because it’s an api call samesite lax doesn’t work, it would need to be samesite none. It works on your web client because they are both served from the exact same domain.

If I have to use fetch, it’s a lot more complicated, downloading the whole file first wouldn’t be a good user experience, so I would have to work out how to stream chunked responses.

KodeStar avatar Sep 27 '21 07:09 KodeStar

It works on your web client because they are both served from the exact same domain.

Not exactly - in development I'm I'm servings from two locations - client in served from webpack dev server - port 8080 and API from port 3000 - browser consider this as two different locations - that's why CORS was introduced in first place.

izderadicka avatar Sep 27 '21 12:09 izderadicka

iirc localhost is accepted, but other domains aren't

KodeStar avatar Sep 27 '21 12:09 KodeStar

Potentially you could get round it by putting them on subdomains of the same main domain, so host the client at https://client.audiosilo.app and the server on https://audioserve.audiosilo.app, then I think they would both be classed as being on the same site. I could set up some kind of dyndns service where https://somekindofhash.audiosilo.app points to the persons IP, it might even work for LAN addresses, I'm not 100% sure on that one (so https://098f6bcd4621d373cade4e832627b4f6.audiosilo.app points to 192.168.10.15 for example), if that worked (again, not sure it would) then there would be no need to reverse proxy for people who just want access within the lan. Otherwise you could point at the WAN address and they would have to port forward or reverse proxy.

KodeStar avatar Sep 27 '21 12:09 KodeStar

I have done some tests, you right localhost is handled differently. Proper way to handle it is per this specification https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie/SameSite - if cookie is SameSite=None; Secure then it works cross site. SameSite is rather new thing, introduced in last few years I think, so it was source of some confusion. I open issue for this https://github.com/izderadicka/audioserve/issues/64

izderadicka avatar Sep 28 '21 06:09 izderadicka

Awesome, thanks Ivan.

KodeStar avatar Sep 28 '21 07:09 KodeStar

I've have updated https://audioserve.zderadicka.eu with new code with cross origin cookies - and playback works. These is still one place with 401 - image fetch from JS, which is missing the Authorization header: image

Is there latest version of your code on https://audioserve.coderior.com? So does it make sense to report things that are not working for me? Most notable was that playback did not continue on next chapter after finishing current one.

Also downloading files to cache is having 401 - again Authorization header is missing: image

izderadicka avatar Sep 28 '21 08:09 izderadicka

Awesome! :D yeah https://audioserve.coderior.com is built from master on each push, so it's always up to date with master (bugs and all), when I'm closer to it being finished, I'll probably start pushing to a dev branch instead and have master as the current release.

I should be able to get those bugs fixed now the cookie is working, I pushed a change earlier which added it for the audio player, which is likely why that worked straight away, I haven't done it for the other urls yet though, should just be a case of adding with credentials to them, rather than passing the bearer.

Edit Nope, I hadn't uploaded that code, so I can only guess it was cached? Maybe from playing it with the built in web client?

KodeStar avatar Sep 28 '21 09:09 KodeStar

Hmm, I'm still not able to play from https://audioserve.zderadicka.eu from localhost? I wonder if that one file was somehow cached, which is why it didn't play the next file?

KodeStar avatar Sep 28 '21 09:09 KodeStar

image The cookie still seems to being added with SameSite Lax

I've tried it both from localhost and from https://audioserve.coderior.com/

KodeStar avatar Sep 28 '21 10:09 KodeStar

Hmm, it was false success on my side, sorry, matter is even more complicated.
This is how it works based on my experiments:

Scenario 1)

  • Opening page in https://audioserve.coderior.com/ and logging in
  • Browser sends POST to https://audioserve.zderadicka.eu/authenticate
  • Back is sent set-cookie with params SameSite=None, Secure
  • Browser sets cookie for location audioserve.coderior.com with SameSite as Lax
  • This cookie is not send to requests to https://audioserve.zderadicka.eu as it is different location

Scenario 2) (Why I initially thought it now works)

  • Opening page https://audioserve.zderadicka.eu and authenticating there
  • Back is send set-cookie with params SameSite=None, Secure
  • Browser sets cookie as secure and with SameSite None for location audioserve.zderadicka.eu
  • Now I go to https://audioserve.coderior.com/
  • And playback works - the cookie is send with request

So in short - cookie can be set only as result of user interaction on that site, setting cookie for other site in request initiated from javascript did not work. It is probably due to some privacy limitations. It's getting so fucking complicated with cookies.

I'll be looking around still, but se per now I think there are two options:

  1. token as URL query parameter
  2. For login redirect to audioserve site and then redirect back - but it'll require some special page for this "federated" login

izderadicka avatar Sep 28 '21 11:09 izderadicka

Next track should work now.

KodeStar avatar Sep 28 '21 12:09 KodeStar

But it looks like it is working for my client where I'm using XHR (with include credentials options)- testing locally cross side - with different names/aliases for localhost.

izderadicka avatar Sep 28 '21 12:09 izderadicka

OK, all is need for things to work to add option credentials:"include" to fetch requests - it's working localhost against any other host. Hope it'll work also for any host against any host, pls merge my PR to check

izderadicka avatar Sep 28 '21 14:09 izderadicka

Done, and it works, I've also fixed the covers not loading :D

KodeStar avatar Sep 28 '21 16:09 KodeStar

Works for me too now with hosted version 👍 , one small issue now is that got this error when clicking on pause button:

pause pressed 86d3ef2.js:1:76678
TypeError: r[(r.length - 1)] is undefined
    NuxtJS 70
d8a3b46.js:2:12272
    NuxtJS 67
update 96 86d3ef2.js:1:33826

izderadicka avatar Sep 29 '21 05:09 izderadicka

Hmm, that would suggest that history isn't being saved when you press play (on pause it updates the last history item with the current timestamp and current seek position) I'll see if I can replicate. The next track issue was due to some refactoring when moving the player events out of the player.vue and onto page.vue and actions.js to facilitate the playback being controlled from a mini player as well when the main player wasn't active, this might be a similar thing.

KodeStar avatar Sep 29 '21 06:09 KodeStar

I can recreate it on the hosted copy by starting a book, then refreshing the page while it's playing, then playing again and pausing, but haven't managed to recreate it on dev yet

KodeStar avatar Sep 29 '21 08:09 KodeStar

I think I have it with starting with completely fresh env - delete all browser data for site.

izderadicka avatar Sep 29 '21 16:09 izderadicka

I pushed up some changes earlier that will hopefully fix it

KodeStar avatar Sep 29 '21 17:09 KodeStar

Great, so next one :-) In mobile browser- there is an bar at bottom, quote cool, but I cannot switch to library, if I click, then library shows for a frac6 of second and then it returns back to home.

izderadicka avatar Sep 29 '21 18:09 izderadicka

yeah, this is due to the description, I have it set so if there is information the right panel pops out on the desktop site, on my test one I have no descriptions in folder so I didn't notice it straight away that it blocks everything on mobile, on your demo site there is a description at every level so it shows up straight away.

I'll work on that now, see if I can come up with a solution, I have an idea of a way to do it.

KodeStar avatar Sep 29 '21 18:09 KodeStar

Ok, version just uploaded hides the description on mobile for now, but I'll try and come up with a better solution, because it would be nice to have a button or something to indicate there is a description and be able to view it

KodeStar avatar Sep 29 '21 19:09 KodeStar