Roku Developer Program

Developers and content creators—a complete solution for growing an audience directly.
cancel
Showing results for 
Search instead for 
Did you mean: 

AddHeader bug in context of videoPlayer (prevents using CloudFront for HLS)

AWS cloudfront requires 3 cookie headers to be set in the request in order to authorize

curl -v -H 'Cookie: CloudFront-Policy=xxxx' -H 'Cookie: CloudFront-Signature=xxxx' -H 'Cookie: CloudFront-Key-Pair-Id=xxxx' https://xxxx.cloudfront.net/index.m3u

in roku

request.AddHeader("Cookie","CloudFront-Policy=xxxx")
request.AddHeader("Cookie","CloudFront-Signature=xxxx")
request.AddHeader("Cookie","CloudFront-Key-Pair-Id=xxx")

This works fine with a roUrlTransfer object and authorizes correctly, however when using a VideoPlayer object AddHeader always replaces any header with the same name, this behavior also happens when setting via an setHttpAgent command.

Add Cookies also doesn't work with CloudFront as although it sends the headers across it seems in a format not recognized by CloudFront, the delimiters in the header are ";" rather than "," which I think is the standard.

httpAgent.EnableCookies()
httpAgent.AddCookies(cookies)
    cookies = [
        {Path:"/", Domain:"xxxx.cloudfront.net", Name: "CloudFront-Policy",Value:"xxxx"},
        {Path:"/", Domain:"xxxx.cloudfront.net", Name:"CloudFront-Signature",Value:"xxxx"},
        {Path:"/", Domain:"xxxx.cloudfront.net", Name:"CloudFront-Key-Pair-Id",Value:"xxxx"}
    ]
0 Kudos
10 Replies
EnTerr
Level 8

Re: AddHeader bug in context of videoPlayer (prevents using CloudFront for HLS)

The correct separator is ";".
Naturally, your code will work better if you reverse the order of setting and using the variable, i.e. 
httpAgent.EnableCookies()
cookies = [
   {Name: "CloudFront-Policy", Value: "xxxx"},
   {Name: "CloudFront-Signature", Value: "xxxx"},
   {Name: "CloudFront-Key-Pair-Id", Value: "xxxx"}
]
httpAgent.AddCookies(cookies)

Also, i don't think there is a point to setting anything else but Name and Value for the request (don't quote be on that "because, Roku" - but FWIW the other keys are when coming back from the server)
0 Kudos

Re: AddHeader bug in context of videoPlayer (prevents using CloudFront for HLS)

Thanks for the reply. I think I can rule out that cookies are the issue then. 

The problem is CloudFront expects 3 distinct http headers each named  "Cookie", and VideoPlayer objects don't support this. 
0 Kudos
EnTerr
Level 8

Re: AddHeader bug in context of videoPlayer (prevents using CloudFront for HLS)

"shibuyashadows" wrote:
The problem is CloudFront expects 3 distinct http headers each named  "Cookie", and VideoPlayer objects don't support this. 

If true, this would be most unusual. 
Because it would fly in the face of https://tools.ietf.org/html/rfc6265#section-5.4 which says

5.4.  The Cookie Header
  The user agent includes stored cookies in the Cookie HTTP request header.
  When the user agent generates an HTTP request, the user agent MUST NOT attach more than one Cookie header field.


Call it leap of faith if you will, but no way CloudFront would demand breaking the RFC.
0 Kudos

Re: AddHeader bug in context of videoPlayer (prevents using CloudFront for HLS)

It could well be non-standards compliant

Here is the reference from Amazon:
https://aws.amazon.com/premiumsupport/k ... s3-origin/

In any case there is inconsistent behavior in Roku between the VideoPlayer and roUrlTransfer components. roUrlTransfer allows multiple headers with the same name and VideoPlayer doesn't.
0 Kudos
EnTerr
Level 8

Re: AddHeader bug in context of videoPlayer (prevents using CloudFront for HLS)

"shibuyashadows" wrote:
It could well be non-standards compliant

Here is the reference from Amazon:
https://aws.amazon.com/premiumsupport/k ... s3-origin/

That's not reference - that is an example. But note if a RFC-broken request works, it does not mean a RFC-compliant cookie header won't work! Odds are both work. To determine what the case is, try a corrected one - i.e. instead of:
curl -v -H 'Cookie: CloudFront-Policy=eyJTdGF0ZW1lbnQiOlt7IlJlc291cmNlIjoiaHR0cHM6Ly9kM2J4Y2k1emplNGJvNi5jbG91ZGZyb250Lm5ldC9pbmRleC5odG1sIiwiQ29uZGl0aW9uIjp7IkRhdGVMZXNzVGhhbiI6eyJBV1M6RXBvY2hUaW1lIjoxNDQyMTgwMTYxfX19XX0_' -H 'Cookie: CloudFront-Signature=ZmKpEDq0AyMwhW6V-seB61zvpGvEsQo2HdOBJQs2qdblimiwtY9clXk4N9odyKu4ACl8nmYQ2ufBXsHcZTecGFS7apNWttORlKYiDJGlgBVQ8XGXF3SXO~buiR3UdqHd6K5-YdwZL1UZMFMSpZb3HNKYetT5Su5Koeq0Vl11smNrz76dsbY-ialGsVYkf4seoMR65UJhLq7TrspHZLEXl7I6SEA7FC7gKQP7-g8vACuZ1jpvniqaJoQphzcV4VWfxLZKifLA9GzjtARJaGqYjNrWkWmTIJ3wFTurMmwTId9~MFfDGwcNULerMKkgKotY630c~T4TpVQFpmwijCoQbg__' -H 'Cookie: CloudFront-Key-Pair-Id=XXXXXXXXXXXXXXXXXXX' https://d123example.cloudfront.net/index.html

do a "monocooque" 8-)
curl -v -H 'Cookie: CloudFront-Policy=eyJTdGF0ZW1lbnQiOlt7IlJlc291cmNlIjoiaHR0cHM6Ly9kM2J4Y2k1emplNGJvNi5jbG91ZGZyb250Lm5ldC9pbmRleC5odG1sIiwiQ29uZGl0aW9uIjp7IkRhdGVMZXNzVGhhbiI6eyJBV1M6RXBvY2hUaW1lIjoxNDQyMTgwMTYxfX19XX0_; CloudFront-Signature=ZmKpEDq0AyMwhW6V-seB61zvpGvEsQo2HdOBJQs2qdblimiwtY9clXk4N9odyKu4ACl8nmYQ2ufBXsHcZTecGFS7apNWttORlKYiDJGlgBVQ8XGXF3SXO~buiR3UdqHd6K5-YdwZL1UZMFMSpZb3HNKYetT5Su5Koeq0Vl11smNrz76dsbY-ialGsVYkf4seoMR65UJhLq7TrspHZLEXl7I6SEA7FC7gKQP7-g8vACuZ1jpvniqaJoQphzcV4VWfxLZKifLA9GzjtARJaGqYjNrWkWmTIJ3wFTurMmwTId9~MFfDGwcNULerMKkgKotY630c~T4TpVQFpmwijCoQbg__; CloudFront-Key-Pair-Id=XXXXXXXXXXXXXXXXXXX' https://d123example.cloudfront.net/index.html


Notice the cookie separator is "; " - semicolon and space, not just semicolon. If Roku is sending ";" without space, that would be a bug, let us know?

On side note - why signed cookie and not signed URL?
0 Kudos

Re: AddHeader bug in context of videoPlayer (prevents using CloudFront for HLS)

you are absolutely right, the curl command worked with the " ;" delimiter, I did the same in a single Cookie http header:


    policy = "CloudFront-Policy=xxxx"
    sig = "CloudFront-Signature=xxxx"
    pairid = "CloudFront-Key-Pair-Id=xxx"
    httpAgent.AddHeader("Cookie",policy + "; " + sig + "; " + pairid)


And it now works correctly. Many thanks for your help on this!


On side note - why signed cookie and not signed URL?

I am using the cookie header so that the subsequent requests for the .ts files will also have the header on the request, I assumed this wasn't possible with the URL property of the VideoPlayer.
0 Kudos
EnTerr
Level 8

Re: AddHeader bug in context of videoPlayer (prevents using CloudFront for HLS)

"shibuyashadows" wrote:
you are absolutely right, the curl command worked with the " ;" delimiter, I did the same in a single Cookie http header:
... And it now works correctly. Many thanks for your help on this!

Ah, this is interesting - why is .AddCookies() failing then?! There might be a bug in Roku's implementation after all. Can you see with a packet sniffer what is going on? I have this gut feeling that maybe they are using ";" as separator instead of the "; " RFC mandate?

Let's exorcise this demon while the iron is hot! :twisted: 
0 Kudos

Re: AddHeader bug in context of videoPlayer (prevents using CloudFront for HLS)

I managed to get AddCookies working also, I had to include the path as "/" and the domain, otherwise roku doesn't send the header. This seems sensible to me from a security point of view, so that if the httpagent calls out to a different domain, the headers won't get sent. I will use this method in my implementation.


    cookies = [
        {Name: "CloudFront-Policy",Value:"xxx",Path:"/", Domain:"xxx.cloudfront.net"},
        {Name:"CloudFront-Signature",Value:"xxx",Path:"/", Domain:"xxx.cloudfront.net"},
        {Name:"CloudFront-Key-Pair-Id",Value:"xxx", Path:"/", Domain:"xxx.cloudfront.net"}
    ]

    httpAgent.EnableCookies()
    httpAgent.AddCookies(cookies)
0 Kudos
EnTerr
Level 8

Re: AddHeader bug in context of videoPlayer (prevents using CloudFront for HLS)

"shibuyashadows" wrote:
I managed to get AddCookies working also, I had to include the path as "/" and the domain, otherwise roku doesn't send the header. This seems sensible to me from a security point of view, so that if the httpagent calls out to a different domain, the headers won't get sent. I will use this method in my implementation.

Huh, amusing. Weird but okay. Great news.
Sorry for giving bad advice earlier of skipping the path and domain... albeit i disclaimed "don't quote me on that" :mrgreen:
0 Kudos