awslabs / unicornflix

Learn how to manage, process, host, and authorize access to streaming video content by building UnicornFlix
Apache License 2.0
203 stars 74 forks source link

Multiple errors when Cloudfront signed URL is configured in amplify #15

Open oswal04 opened 4 years ago

oswal04 commented 4 years ago

When Cloudfront signed url is configured in "amplify video add" section, after completing all the steps in the workshop, there are multiple errors while viewing the video.

  1. Access to XMLHttpRequest at 'https://xyz.cloudfront.net/output/sampleVideo.m3u8' from origin 'http://ec2-public-ip:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

  2. GET https://xyz.cloudfront.net/output/sampleVideo.m3u8 403 (Forbidden) It seems like the app is not getting the signed cloudfront url.

  3. After some debugging in lambda console I tried getting the cloudfront signed url but it gives me "Error> AccessDenied

    Access Denied some-request-id xyz-hostid

    "

Any help is highly appreciated as I'm trying to help my customer adopt this solution.

mattorp commented 4 years ago

Did you find a solution to this?

rubelwtrility commented 4 years ago

I believe you have to use signed cookies instead of signed url. The signed url give you access to the m3u8 file, but not all subsequent files.

sanjukris commented 4 years ago

Signed URL is working fine in Chrome(Mac & Android) but not on Safari (Mac) and all browsers on iPhone. Is this a limitation with VideoJs? Wondering if any other commercial video player is available that can support signed S3 URLs. Also, anyone verified if Signed Cookies are working across all browsers?

roblittle commented 3 years ago

I"m having the exact same issue, in that the secure url can read the list m3u8 file ( via curl, or nodejs + hls.js programatically), but as soon as the individual stream file is selected, it either a) 403 forbidden (via curl) or b) No 'Access-Control-Allow-Origin'

I've spent almost 2 days, fully checking everything, from CloudFront Behaviours / Whitelist config, to S3 bucket policy for the arn for the cloudfront user. everything looks fine.

HELP pleasse

roblittle commented 3 years ago

I believe you have to use signed cookies instead of signed url. The signed url give you access to the m3u8 file, but not all subsequent files.

The tutorial/lab set this up all with signed urls. And the ReactJS client app, using the Cognito user that i'm using via node programatically to authenticate, does not have CORS issues, and can stream the individual .m3u8 content files without a 403.

So i'm not convinced the setup is wrong, or how would the ReactJS client, stream the videos securely, fine, without 403 or CORS...

but something is missing from my understanding, and testing, using curl and nodeJS + hls.js ... cause i see the exact same as others above here

sanjukris commented 3 years ago

The fix listed here is working fine on Chrome (Mac and Android), unfortunately not on any of iOS browsers and Safari (Mac). I guess the reason being is it's not invoking videojs.Hls.xhr.beforeRequest = function (options) to append the token for playback files. If the Signed Cookie is the magic solution for this problem, appreciate it if someone can provide snippets on how to pass the cookies with the .m3u8 and .ts files.... at least on iOS Chrome.

roblittle commented 3 years ago

We aren't alone https://stackoverflow.com/questions/64166589/stream-aws-s3-hls-videos-in-ios-browsers/64988224#64988224

roblittle commented 3 years ago

The fix listed here is working fine on Chrome (Mac and Android), unfortunately not on any of iOS browsers and Safari (Mac). I guess the reason being is it's not invoking videojs.Hls.xhr.beforeRequest = function (options) to append the token for playback files. If the Signed Cookie is the magic solution for this problem, appreciate it if someone can provide snippets on how to pass the cookies with the .m3u8 and .ts files.... at least on iOS Chrome.

I've refactored my code again, used a ReactJS video upload/download sample code, that works - and am now at the safari blocker regarding the options not being parsed by safari to see the security options.

sigh

roblittle commented 3 years ago

I have this fully solved, and working now for Chrome and Safari / iOS based browsers.
I will summarize everything i did (and it was pretty complicated end to end), and post it here soon for everyone else.

coles notes: I fully solved this, literally just now, after spending upwards of 90hours in total on this issue. There are many many layers of configuration. I will try to write up a full guide of how i fixed this, after i audit and write down all the steps, but the main eureka points for me to get you started were - setting up cname to CF (like cf.domain.com) setting cookie to work for subdomains ie .domain.com and then configuring the CF Distribution to use this cname (after updating the domain cert to include this subdomain), and to forward 3 specific headers to S3: origin, req headers + req method
oh and withCredentials:true needs to be used on the call that returns the cookies, or they won't be available as you expect. I think those were the major bullets, and i will correlate everything i did, and write a full how did i fix this solution, soon (later today hopefully). This was one of thee most complicated integrations i've ever done as a developer, and the documentation was all over the place from AWS. –

roblittle commented 3 years ago

solution walk through posted https://stackoverflow.com/a/64988224/1207732 let me know if you need any further assistance

roblittle commented 3 years ago

Signed URL is working fine in Chrome(Mac & Android) but not on Safari (Mac) and all browsers on iPhone. Is this a limitation with VideoJs? Wondering if any other commercial video player is available that can support signed S3 URLs. Also, anyone verified if Signed Cookies are working across all browsers?

it doesn't work across browsers with just signed urls, or signed cookies. For me, i server the signed url(s) but issue cookies based on the urls at the same time, so both Safari/iOS and the rest of the browsers are happy. See https://stackoverflow.com/a/64988224/1207732 for my attempted walk through of my solution that i finally engineered.

roblittle commented 3 years ago

Did you find a solution to this?

let me know if https://stackoverflow.com/a/64988224/1207732 helps you out

skfaisal93 commented 3 years ago

@roblittle I have followed the same instructions on AWS console and tried to implement the same on JS + PHP but still, the video does not play:

I set headers in PHP like this:

header('Access-Control-Allow-Credentials: true'); header('Access-Control-Allow-Origin: https://protected.onlinevideobooks.com');

Here is the JS code:

<link href="//vjs.zencdn.net/7.8.2/video-js.min.css" rel="stylesheet">
<script src="//vjs.zencdn.net/7.8.2/video.min.js"></script>

      <video
        id="my-player"
        class="video-js"
        controls
        preload="auto"
        poster="//vjs.zencdn.net/v/oceans.png"
        data-setup='{}'
        width=600 height=300>
    </video>
        <script type="text/javascript">

        var player = videojs('my-player');
        videojs.Hls.xhr.beforeRequest = function (options) {
          options.uri = `${options.uri}${videojs.getAllPlayers()[0].options().token}`;
          return options;
         };

player.ready(function() {
        player.src({
          src: 'https://protected.onlinevideobooks.com/output-plain/art.m3u8',
          type: 'application/x-mpegURL'
        });
      });

I also confirmed that signed cookies are setting in the browser without any issue. I tried to access the image file through the same CloudFront distribution and it is a working file. Also, I am able to download m3u8 file, However video does not play also cookies don't send in the request header too.

Can you please guide me on what I am doing wrong?

Thanx in advance.

tsenguunchik commented 3 years ago

@roblittle I've also followed the detailed guide and wasn't able to play the video.

This is asking too much, but would it be possible for you to record a video on youtube for your approach?

Thank you so much!

skfaisal93 commented 2 years ago

@tsenguunchik I resolved it, there was some CORS policy issue. mail me at f.shaikh1993@gmail.com and I will help you as I hardly visit here.