Wednesday, August 29, 2007

HTTP Request Headers and Flash

I've been doing a lot of Flash/Flex work over the past few months. I recently had a colleague ask me if a SWF embedded in a page has access to the cookies for that domain. I knew the answer was no, and said as much. Then I started thinking, that just seems wrong. Why doesn't a SWF have access to cookies, and for that matter, all the HTTP headers that were sent as part of the request for the SWF?

It's easy to create a simple page with a SWF embedded in it and load up Firebug to watch the HTTP traffic. I created a simple two page app to experiment with this. On the first page, I used so JavaScript to write a cookie. By the way, this is annoyingly mundane. I know there are JS libraries for abstracting this and providing a clean API, but you would think that IE or Mozilla would have added an extension to JavaScript that does exactly this. Having to do document.cookie.indexOf(...) and document.cookie.substring(...) all the time is just ridiculous.

Back to the app. After setting some cookies, there is a link that goes to page two. Page two includes an embedded SWF. Watching the traffic on page two, I could clearly see cookies, user-agents, referrers, etc. all being sent as part of the HTTP request for the SWF. One interesting thing is that the referrer was page two, not page one. That makes sense, though.

So everything is clearly there, it's just not available to the SWF runtime. Any parameters on the query string are available. In Flex you can get to them using Application.application.parameters. This gives you a classic ActionScript Object, i.e. an associative array. So if you put the URL for the SWF as http:///widget.swf?foo=bar then you can write AS code like Application.application.parameters.foo. So not all of the HTTP request is being thrown away, though the headers certainly are.

All I can think of is that this is a security issue. It creates other potential security problems though. Imagine if page one in my app was a login page, and page two was some kind of personalized home page. A lot of websites use cookies for authentication, and that authentication is not being passed to the SWF. What's a developer to do? There are lots of options, but you can imagine some very unsavory and horribly insecure ones.

Anyways, I thought maybe I was wrong all along, and just didn't know what I was talking about. It certainly wouldn't be the first time, and especially considering I didn't know any Flash 12 months ago. So I posted the question on Flexcoders... It's been about 24 hours with no responses, which usually means nobody knows the answer.

6 comments:

Josh said...

I am running into the same problem now. I just want to get the address of the referer. Did you ever figure this out? I would much appreciate it.
Thanks!

Michael said...

Actually I wrote more about this recently: http://fupeg.blogspot.com/2008/01/flash-and-http-headers-redux.html . The short of it is that not all browsers make the headers available to the Flash Player, so the Flash Player does not expose this. I don't which browsers, but I'm guessing older ones. It is really too bad that the Flash Player doesn't provide this when the browsers do support it, and just give back nulls or something when they don't.

If you control the page embedding the SWF, then you can expose of all of this through JavaScript and use ExternalInterface.

Josh said...

Thanks for the response. I thought that might be the case. It seems like I should be able to set a httprequest that should grab the original post!

Maybe I can make a php wrapper that grabs the referrer and posts it after a few seconds. Then a httprequest that grabs it as post data? What do you think of that idea? I'll let you know if it works.

Josh said...

I ended up having to forward the request to my RoR controller, which logged the time and then forwarded to the flex app. Which grabbing the most recent urlreferer onload by the flex object. Did the trick, just needs some ironing out! I think if I can ruby to grab some session when my flex app makes the call to get the url referer I can get more accurate.

Michael said...

Interesting approach. I take it that your SWF could be on lots of different pages, and you are trying to track who is using it? Your approach is sound. Any HTTP requests from your SWF to your server should include the referrer from the original page, since the Flash Player relies on the browser to make the call.

One thing to note is that the host page can disable what you are doing. They can turn networking off in the embed code. That might break other functionality in your SWF anyways.

If you are (web) hosting the SWF, couldn't you also just watch the Apache logs? What I mean is that if the URL to your SWF is http://www.myserver.com/widget.swf then your web server's logs would have the referrers to all requests for your SWF.

Finally, one other evil hack you could do is to execute JavaScript to do the same thing, but without the need for a server. When you call ExternalInterface (or even navigateToUrl) you can inject JavaSript into the page, by doing document.write. That JavaScript can then be invoked to extract HTTP header info and call an ActionScript method with the data. Obviously they have to enable script access in the embedding code (allowScriptAccess="always") ... And this is a really evil thing to do!

Android app developers said...

This is one of the attractive post.I like your blog clarity.This is one of the knowledgeable post.