Use Case I've been working on a project with a team of some of our really talented Flash developers (props Ben, Leon and Gabriel) where a Flex app being served from a non-secure URL via plain HTTP needs to connect to and consume data from another server via HTTPS and have run into some issues and a workaround that I'd like to share. For that particular project, the other server is a SOAP service running behind SSL with a Flex app served over HTTP consuming those services. However, these concepts also apply to any external data consumed by the Flash Player. A simplified diagram of the system is below:
Pretty basic use case, right? Should be pretty straightforward once the usual suspects are addressed as follows, right? No, of course not, otherwise this article wouldn't actually be helpful. I'll start with the server environment and SSL certificates.
SSL Certificates On the development boxes that I've been using, self-signed certificates are installed, which means that an SSL certificate is created DIY on the server rather than purchasing one from a certificate authority like Verisign, Thawte, etc. This is a common practice for development systems, internal systems and others where end-users may not be concerned that the certificate was not issued by a certificate authority.
Because of that, when pointing a browser (in this case Safari, FF or IE6 are the ones that I'm testing against) at for example https://dev.services.com/, a pop-up application window with a security warning appears asking if the certificate should be accepted. (This is an important point that I'll be coming back to) Clicking yes acknowledges that you are aware of the security implications of interacting with a server that has one or more of the following characteristics:
- The SSL certificate has expired
- The domain of the server does not match the domain of the SSL certificate
- The SSL certificate is not signed by a certificate authority
A Special Browser from Special People With IE7, the above is almost identical, with one important distinction. That is that IE7 does not use a different application window to display the security warning. It redirects to a local page that displays the security warning as the following screen capture illustrates:
As we'll see later, this comes back to bite us in the ass. However, let's take at all the pieces that need to come together to make this work.
Crossdomain.xml File As with all server-to-server communication, a crossdomain.xml file is required on the https://dev.services.com so that the Flex app on http://dev.application.com can talk to it. For testing on the development box, the crossdomain.xml as such:
In this case, the secure="false" attribute is allegedly supposed to signal the Flash Player to ignore certificate warnings and allow the loading of content from the secure context. I have found a wealth of contradictory information on this topic and because it doesn't really seem to be clear, since this is a development server, I'm just going to leave it in there because I know that the certificate does not match the domain and is self-signed. This attribute should be removed on production servers, as according to Adobe, it may compromise security:
"A secure server that allows access to movies hosted via a non-secure protocol It is not advisable to permit HTTP content to access HTTPS content. This practice can compromise the security offered by HTTPS."
This comment is seemingly contradictory, so I'm not entirely certain that it is true. I can understand how loading from HTTP into HTTPS is a security issue, but not the other way around.
HTTP Headers So, despite having this configured with secure="false", there is another aspect to this that will be a pain if you test in Firefox and then try to get it to work in any version of Internet Explorer, as it will fail silently in IE. That is the issue of HTTP headers that are sent by a web server in response to a request from a browser. In IE, because it is the short bus of browsers, any HTTP responses sent from a secure context to an insecure one are ignored. I don't know enough about the inner workings of IE to know why, however, it fails silently.
To get around this and allow HTTP responses to be received over SSL from a server, it is necessary to change either configuration at the web server level on https://dev.services.com or set the headers at a code level to ensure that the proper headers are being sent with HTTP responses. That HTTP header is as follows:
There is a great deal of disagreement and contradiction on this topic, as can be seen with nearly every comment related to this blog post. However, according to my testing, and the word of my esteemed colleague, Robert Reinhardt, this is the one that indeed works.
The IE7 Issue Now, with all of that set up, it should be possible to load data into the Flex app from the secured domain via HTTPS. In testing this with Firefox, Safari and IE6, once the crossdomain.xml is requested, a security warning is triggered that then asks the user to accept the certificate for the secure domain that the Flash Player is attempting to communicate with. If the certificate is accepted, the crossdomain.xml file is loaded and then the Flash Player can access resources on that server.
In attempting this in a server environment where the certificate triggers the certificate security warning, the following following error is thrown (if the debug version is installed or errors are trapped and traced out, otherwise it just fails silently):
[RPC Fault faultString="Security error accessing url" faultCode="Channel.Security.Error" faultDetail="Destination: DefaultHTTP"]
Using a tool like IEHTTPHeaders or IEWatch Professional and looking at the HTTP headers and what requests are made, it becomes apparent that the crossdomain.xml is not being loaded at all. It shows its status as "aborted", meaning that IE7 refuses to actually load it. As a result, this is the reason that the call is failing. The only ways around this that I have found are:
- Navigate to the server that is hosting the crossdomain.xml file manually and accept the certificate then navigate back to the page with the Flash Player and then try to access the other server.
- Make sure that the server that is being connected to does not throw any certificate security warnings in IE7.