Open djsjr opened 3 years ago
For anyone with a similar problem, I was able to take the token obtained through an API call, separate it into substrings for the Policy, KeyIdPair, and Signature, and then create a Map<String, String> with the [same format used here].(https://stackoverflow.com/questions/60773608/flutter-how-to-set-cloud-front-cookie-in-expo-video-player-plugin)
Take those substrings from the token string, make a map, and pass into the headers param.
String cookieValue = '';
cookieValue += "CloudFront-Policy=" + policy + ";";
cookieValue += "CloudFront-Signature=" + signature + ";";
cookieValue += "CloudFront-Key-Pair-Id=" + keyPaidId + ";";
Map<String, String> cookie = {'Cookie': cookieValue};
_videoPlayerController = VideoPlayerController.network(url, httpHeaders: cookie);
Video player is now working.
@djsjr thanks for sharing your problem and solution with the community. Do you want to keep this ticket open to track a feature for optional cookie based support? Otherwise we can close as resolved. If you think it's appropriate, we can also add a note to the docs.
Considering CloudFront specifically recommended signed cookies for HLS content, it'd probably be a good idea to add it as an option at least.
I do think a note on converting the signedURL to a cookie format could be helpful to others in the meantime. The trick is appending the params together with semi colons as one string and passing it as a single header, as I did. I've only tried it in Flutter, but others have made this work with ExoPlayer as well.
Did you test this on an actual iphone?
@tsenguunchik The workaround? Yes
Wow that is surprising. I'm trying to use this exact thing on web with JS but failing miserably.
@tsenguunchik I tested on actual iPhone 6S using React Native with Expo SDK v45 and expo-av and it works.
This is a simplified version of the example in Expo Video.
export default function App() {
const video = React.useRef(null);
const cookie = `CloudFront-Policy=${policy};CloudFront-Signature=${signature};CloudFront-Key-Pair-Id=${keyPairId}`;
const headers = { Cookie: cookie };
const source = { uri: foo, headers: headers };
return (
<View
<Video
ref={video}
source={source}
/>
</View>
);
}
Note: policy
, signature
and keyPairId
must be parsed from the token obtained through GraphQL API call.
Sample regex to obtain these variables:
const policy = /[?&]Policy=([A-Za-z0-9-_~]+)/.exec(token)[1];
const signature = /[?&]Signature=([A-Za-z0-9-_~]+)/.exec(token)[1];
const keyPairId = /[?&]Key-Pair-Id=(\w+)/.exec(token)[1];
Thank you @djsjr for sharing your achievements.
I cannot currently use signed URLs with HLS videos in my flutter app because the video players available to flutter do not allow for appending tokens to the end of each request. I realized this was necessary from #236.
The standard flutter video player (as well as the widely used “just audio” player) both have a parameter for a map of http headers. Therefore, I suggest allowing content protection via signed cookies - which I believe would allow me to successfully access protected content by providing the signed cookie to the player.
if I am incorrect about this, or if there is a way to change the current set up to fulfill my need, please let me know!