7

I have been trying to get this to run correctly so days now with no luck.

I have created a custom audio player, that accesses an MP3 on a S3 Amazon server. The audio player has custom controls enabled by Javascript, and a Audio Visualizer made possible by the Web Audio API.

Now the problem I am running into is this: Work fine on Chrome. Safari out right says it can't run the Web Audio API, but the audio will still play. In Firefox, the entire thing shuts down. Click play... nothing. I thought it was a CORS issue, so we set the proper headers on the server and still nothing. BUT... if I deactivate the Web Audio API visualizer, then I can get the player to play just fine.

http://jsfiddle.net/murphy1976/yqqf7uL1/1/

Here is my jFiddle. I have separated the Audio Player controls Script from the Visualizer Script with comments so you can see how it will work in Firefox, and how it will NOT work in Firefox.

I read somewhere that this issue that I'm running into MAY be a bug with Firefox. I just want to make sure so that I can stop beating my skull over this.

Could I put a call to CORS here?:

<source crossorigin="anonymous" src="audioFiles/35022797.mp3" id="srcMP3" type="audio/mp3">
Murphy1976
  • 1,415
  • 8
  • 40
  • 88
  • Does your server serve the audio resource with an `Access-Control-Allow-Origin: *` response header? Generally, a script cannot read cross-origin resources unless it is allowed by a CORS response header from the server when the the resource is served. (If you are not serving CORS responses, it appears that Chrome is wrong here to allow you to read the resource.) – apsillers Dec 11 '14 at 19:31
  • @apsillers we have followed the proper steps outlined here: http://docs.aws.amazon.com/AmazonS3/latest/dev/cors.html and are still unable to get that header. All we can get is a Error: Access Denied. I guess I am confused as to why I don't get this error in Chrome or Safari. – Murphy1976 Dec 11 '14 at 19:41
  • It appears that Firefox ignores CORS headers that should allow it to read cross-origin audio files, per [this bug](https://bugzilla.mozilla.org/show_bug.cgi?id=937718). It appears that Chrome is too permissive (plays even when CORS is missing) and Firefox is too strict (does not play even when CORS is present). Is it possible to host the media on the same origin as your player? – apsillers Dec 11 '14 at 20:03
  • Unfortunately, due to the nature of our business, that is not an option. If its a bug, then it's a bug, and we just have to wait until it is resolved or fixed. Thank you once again for your assistance. – Murphy1976 Dec 11 '14 at 20:10
  • The Web Audio API has a ways to go before it will see widespread mature implementation (that bug is over a year old). A possible solution you could implement now would be to use a same-origin [reverse proxy](http://stackoverflow.com/a/3076439/710446) to fetch the media (e.g., `http://myorigin.com/fetch?path=http://otherorigin.com/song.mp3`). You'd need to set up a server to fetch the media and serve it on your origin. (Note it will not work for credential-protected content.) – apsillers Dec 11 '14 at 20:14
  • @apsillers My real question is why. Why does this work without the Web Audio API, but fail when the Web Audio API is in place? – Murphy1976 Dec 11 '14 at 20:19
  • @apsillers. OH. yeah. I don't think that will be a solution either. I'll talk to our back end people, but that may be too much to ask for 'round these here parts. Worst case scenario is the audio player doesn't have a visualizer. I think as long as it has the media playing, that should be enough. – Murphy1976 Dec 11 '14 at 20:21
  • @apsillers This question has been extremely helpful! (+1). I'm wondering though how I might set the CORS response header on my own web server. I've built my own webserver with Ubuntu Mate 14.04 and LAMP with Apache2 and I've been banging the wall for many hours trying to figure this out. Any suggestions? Thank you :) – www139 Jul 23 '16 at 15:27

2 Answers2

27

The same-origin policy says that scripts run on some origin cannot read resources from another origin. (An origin is a domain, plus a scheme and port, like http://foo.example.com:80.)

Note that the same-origin policy does not prevent cross-origin media from being displayed to the user. Rather, it prevents scripts from programmatically reading cross-origin resources. Consider the <img> tag: a page on example.com can show a cross-origin image from other.com, but a script on example.com's page cannot read the contents of that image. The user can see it; the page cannot.

The Web Audio API can read the contents of audio files. If an audio file is from a different origin, this kind of reading is not allow by the same-origin policy. A user can listen to a cross-origin audio file, but a script on the page cannot read the contents of the file. When you attempt to feed a cross-origin audio file into an analyzer script (e.g., so that you can draw a visualization on a canvas), the same-origin policy should stop you. You are attempting to violate the same-origin policy, and the browser is correctly stopping you by refusing to play the audio in way that would allow you to read the file contents.

Note that Chrome does not prevent such cross-origin file reading for audio files, and this is incorrect behavior.

The correct solution is to have your media servers serve the audio files with a CORS Access-Control-Allow-Origin: * HTTP response header. However, this currently does not work in Firefox, which is incorrect behavior. If Firefox hopes to have a compliant implementation, this will be fixed eventually.

apsillers
  • 112,806
  • 17
  • 235
  • 239
  • 9
    [As of Version 42](https://code.google.com/p/chromium/issues/detail?id=462998), Chrome correctly blocks cross-origin file access using the Web Audio API. You can create a simple `Audio` object to play cross-origin audio, but you cannot create a `MediaElementAudioSourceNode` from that to, say, analyze the raw audio data. – Ian Lesperance Mar 12 '15 at 04:37
  • A good follow up on what your options are: http://stackoverflow.com/questions/30603872/how-can-i-avoid-cors-restriction-for-web-audio-api – Anson Kao Jun 08 '15 at 01:07
  • I understand your answer technically, but how is this a security concern? Or is it not about security? (I'm referring to reading contents of an MP3 files for example). Or is it about protecting other people's assets, and not about security? – trusktr Dec 29 '17 at 06:41
  • 1
    Also, even though I have the header set to "*" for a file from one domain, Chrome incorrectly continues to block me from reading the file on another domain. (It is an MP3 file). For example, see this conversation: https://twitter.com/CodePen/status/945810502399049728?s=09 – trusktr Dec 29 '17 at 06:44
  • Is this a CORS bug in Chrome? https://bugs.chromium.org/p/chromium/issues/detail?id=798043 Or do I just not know what I'm doing? – trusktr Dec 29 '17 at 07:10
  • @truskr The simplest security example I can think of is: suppose you have an internet-enabled security camera on your home network, and it exposes past recordings to other devices on your network via a Web API. No website should be able to tell your computer's browser to load a recording from that camera's Web server and then read it with the Audio API and send it somewhere under the website's control. – apsillers Dec 29 '17 at 16:45
  • @trusktr I found [this Q&A](https://stackoverflow.com/questions/31308679/mediaelementaudiosource-outputs-zeros-due-to-cors-access-restrictions-local-mp3) which suggests you need to include the property `crossOrigin=true` (or `crossorigin=true`?) in your ` – apsillers Dec 29 '17 at 17:33
  • @aspillers I see, it's not that audio is insecure for the user's browser, it's about not letting any website (served from any domain) access content that is meant to be accessed only from sites from specific domains. – trusktr Jan 02 '18 at 08:25
  • @IanLesperance I am blocked from reading the raw bytes of a streaming radio station -- but I can play the station? -- this seems crazy. If I want the raw bytes I guess I have to write an app in c# and deploy to appstore? – patrick Nov 14 '22 at 19:44
  • @patrick That's correct -- you are able to run your own streaming application to see how the stream looks to you as an uncredentialed observer from your own point on the topology of the Internet, but your script is not permitted to view how the stream looks to one specific user (who may fetch it with cookies or have privileged local-network access to the resource), unless the resource allows this privilege via CORS headers – apsillers Nov 14 '22 at 22:31
  • @apsillers I think the local-network access point isn't so strong because they could run an Android App off their wi-fi which could exfiltrate an .mp3. The only case where it does anything useful seems to be cookies, since those won't be present in an Android app. – patrick Nov 14 '22 at 23:40
  • @patrick Absolutely -- but I have very different expectations about the privacy of my network visibility when I visit a website versus install an app – apsillers Nov 15 '22 at 00:40
0

Confirmed that there is a bug in Firefox for using the createMediaElementSource method on a cross domain source:

https://bugzilla.mozilla.org/show_bug.cgi?id=937718

mrbmc
  • 21
  • 3