SolidOS / solid-panes

A set of core solid-compatible apps based on solid-ui
MIT License
100 stars 42 forks source link

Protected music & video files get 401 on CSS even if authenticated #373

Closed timbl closed 1 year ago

timbl commented 1 year ago

When you try to play misc files which need tyou to be logged in, CSS returns 401 error and the browwser does nothing about it. Just like the problem with images in IMG tags in the html.

eg fails:

https://timbl.com/timbl/Public/Test/Protected/Les_Hayden_-_01_-_Gift_Horse.mp3_.mp3

compare with public unprotected file does nt have the same problem

https://timbl.com/timbl/Public/Test/Music/Les%20Hayden/Proverbs/Les_Hayden_-_01_-_Gift_Horse.mp3_.mp3

josephguillaume commented 1 year ago

Presumably this is the line that needs to change: https://github.com/SolidOS/solid-panes/blob/32b73b7d09660ebf8ec1fed046cd06e9b07beabe/src/audio/audioPane.js#L159

bourgeoa commented 1 year ago

@josephguillaume yes We used blob for images. But we may have a size issue with audio and surely video Are you interested to make a PR. https://developer.mozilla.org/en-US/docs/Web/API/Streams_API/Using_readable_streams

I have created the https://github.com/SolidOS/solid-panes/tree/fetchMediaStreams branch

josephguillaume commented 1 year ago

I've never worked with ReadableStream before, so I might start by reading up and then see. Thanks!

bourgeoa commented 1 year ago

Found some documentation using fetch and new MediaSource.

There is also new MediaStream but seems more related to camera streams

josephguillaume commented 1 year ago

Thanks. Everything I found so far was similarly involved. I even found some that loaded their own codec libraries, e.g. https://github.com/AnthumChris/fetch-stream-audio

This one was the clearest but still ends up requiring specifying a codec, and the example uses split audio and video streams (hopefully not necessary!).

I'm not sure I'll get to it today, so if the solution becomes clear to you, please do go ahead...

The use of streams of variable quality was interesting too. I've already been thinking with slideshow that my photos are too large and take too long to load. Depending on bandwidth, the same concept applies to audio and video streaming. It'd be interesting to see what we can do about this, potentially even without server support. Definitely a new longer term issue though...

josephguillaume commented 1 year ago

Given how simple the audio tag is and how complex the Mediasource is, I wonder whether we should be using this bug to explore the comment:

https://forum.solidproject.org/t/is-it-secure-for-pods-to-serve-html-files/6379/9 "For handling files, I do think that Solid will need a way to request from a Server a time boxed & authentication bound URL for a resource, such that that URL can be used directly via browser native elements (img, audio, video, etc)"

A currently possible client-side solution would involve temporarily granting public access to the resource.

If we had server-side support to specify redirects (https://github.com/solid/specification/issues/136) then we could issue a temporary unguessable url to provide a level of indirection/discourage linking directly to the resource.

If we had server-side support to specify symlink-like behaviours within a pod, then the temporary URL could directly return the resource.

To avoid completely public access, the server could support cookie or other built-in auth beyond the spec??

I.e. If solving this bug is urgent then maybe we just use the ACL solution. If it's not urgent, maybe we let the spec catch up?

bourgeoa commented 1 year ago

Resolved with the authenticated fetch blob solution used for tag. This is not a streaming solution. The file is fully loaded before reading.

bourgeoa commented 1 year ago

For the records I tried with new mediaSource but this did not add any reading while streaming and added mimeType complexity

      // https://stackoverflow.com/questions/39275481/chrome-to-play-a-video-that-is-being-downloaded-via-fetch-xhr/68778572#68778572
      const mediaSource = new MediaSource();
      mediaSource.addEventListener('sourceopen', async () => {
        const sourceBuffer = mediaSource.addSourceBuffer('video/mp4');      
        const response = await kb.fetcher._fetch(subject.uri)
        const body = response.body
        const reader = body.getReader()      
        let streamNotDone = true;      
        while (streamNotDone) {      
          const {value, done} = await reader.read();          
          if (done) {streamNotDone = false; break;}
          await new Promise((resolve, reject) => {
            sourceBuffer.appendBuffer(value)
            sourceBuffer.onupdateend = (() => {
              resolve(true);
            })
          }) 
        }
      })
    video.setAttribute('src', URL.createObjectURL(mediaSource))
josephguillaume commented 1 year ago

Another possible solution came up that I wasn't aware of: apparently a service worker could be used to provide authenticated fetch behaviour, and it reportedly at least works on img tags.

https://github.com/solid/solid/issues/143#issuecomment-390421966

A fair bit of work would be needed still for the databrowser to install the service worker, and I believe we'd also need to confirm a secure way to pass tokens or an authenticated fetch function from the main thread to the service worker.