Cross-Domain Requests in Adobe AIR - Security Series #13

At cf.Objective() this last week, one of the topics of discussion after Samer Sadek's excellent Adobe AIR presentation was about cross-domain restrictions in Adobe AIR applications written with JavaScript. I do not know if this discussion is relevant with AIR applications written with Flex.

As many may know, and if you don't you should read up on this, most browsers implement a "same-origin" policy on JavaScript run within the browser. This means that JavaScript is free to use any resource available from within the domain that it is running, but it cannot use remote resources.

Let's look at an example of this.

I have placed a simple CFC on my web server called RemoteObject.cfc. This CFC contains a single remote method called getRemoteData().


<cfcomponent output="false">
    <cffunction name="getRemoteData" access="remote" returntype="struct">
        <cfset var myData = StructNew() />
        
        <cfset myData = {fname="Ben", lname="Nadel", status="Awesome"} />
        <cfsetting showdebugoutput="false">
        <cfreturn myData />
    </cffunction>
</cfcomponent>

So we have a method here that will return a struct when called. The struct contains three values fname, lname and status.

Next, I create my JavaScript in my index.htm file to make the remote call:


//Get Remote Data
$(function() {
    $.ajax({
        url: 'http://12robots.com/RemoteObject.cfc',
        data: {'method':'getRemoteData', 'returnformat':'json'},
        dataType: 'json',
        success: function(data, msg) {
            alert(data.FNAME + " " + data.LNAME + " is " + data.STATUS);
        },
    });
});

Here I am using jQuery to make a simple Ajax request to my remote server as soon as the page is loaded. I am passing in the method name and telling ColdFusion that I would like it to return the struct as JSON. The dataType attribute is telling jQuery that the data being returned is JSON. This allows jQuery to turn it into an object. Finally, on success I am going to create a pop-up of the returned data, except we will never get that far.

When I load my index.htm with this block of JavaScript running automatically, I get this error in FireBug:


Access to restricted URI denied" code: "1012

Anyone who has tried to load data from a remote site with JavaScript is familiar with this error message. This is the browser's enforcement of the single-origin policy. My index.htm is being run from http://localhost:81 and it is trying to receive data from http://12robots.com:80.

There are ways around this restriction, but that is not what we were talking about at cf.Objective(). We were talking about whether or not the same-origin policy exists in an Adobe AIR application.

The simple answer is, No.

Adobe AIR does not enforce the single-origin policy in applications. Functionally, this is a good thing. It means that we can access data from multiple sources and bring that data to a desktop application. Without this functionality, we would be VERY limited in what we could do with our AIR applications.

This also means that the security in an AIR application is a little looser and that we need to make sure, as responsible developers, that we are only pulling data from trusted sources.

So I've taken my index.htm file and places it into an AIR application. I have done nothing else with it. Now, when I run that AIR application, here is the result:

Comments
Rick O's Gravatar It would be nice if we could specify a list of domains in our Application.xml that the sandbox could lock down to. That'd make me feel a whole lot better about the lack of cross-domain restrictions.

(But at the same time, I'm still waiting for a way to tell the sandbox that, no, I don't access the filesystem so there's no need to freak out the user by telling them that my app wants UNRESTRICTED SYSTEM ACCESS OMG!. Not holding my breath, though.)
# Posted By Rick O | 5/18/09 1:43 PM
Jason Dean's Gravatar @Rick, yeah, I'm not sure what to think is the best policy with this. If it is possible, it might be nice to restrict the application to calling only specific domains.

As for the file system access, I have been thinking about that one a lot lately. It seems to me that an Adobe AIR app doesn't have any more unrestricted access than any other desktop application. I'm not a desktop developer (outside of AIR) but I would think that any desktop app could have the same "security issue" and that we as computer users really need to think a little more about what we are installing instead of willy-nilly installing any app that looks like it does something cool, whether it is AIR or C++, or whatever.
# Posted By Jason Dean | 5/18/09 1:50 PM
Samer Sadek's Gravatar Hey Jason, This is interesting. I guess the logic is that it is common to put resources on the same server where the web app is running, but how would you put them on the user's desktop?
If I have some time tomorrow, I'll test it with a mxml AIR app.
It was great seeing you at CFO
# Posted By Samer Sadek | 5/18/09 9:09 PM
Jason Dean's Gravatar @Samer, I think you are exactly right. AIR would be pretty useless without the ability for remote calls. I'll look forward to seeing what you learn with Flex.

If I remember correctly, Flex in the browser has a Cross-Site restrictions in place that can be overcome with a cross domain policy file. I'll be curios to see if that is needed for a Flex AIR app as well.
# Posted By Jason Dean | 5/19/09 12:41 PM
Samer Sadek's Gravatar Thanks Jason. So I did a quick test. As you said, got a security error trying to access a cfc from the flex app, but was able to access it from the air app.
When I ran the swf file of the flex app by itself (outside of the browser), it ran fine with no error. Found this article
http://kb2.adobe.com/cps/142/tn_14213.html
that confirms "Note: This security feature does not affect Flash movies playing in stand-alone projectors."
If only I read the documentation!


Here is the code that I tested:
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"; layout="absolute">
   <mx:Script>
   <![CDATA[
      import mx.rpc.events.ResultEvent;
      import mx.rpc.events.FaultEvent;
      import mx.controls.Alert;

      private function handleResult(event:ResultEvent):void {
         Alert.show(event.message.body.toString(), "Success");
         }

      private function handleFault(event:FaultEvent):void {
         Alert.show(event.fault.message, "Error");
         }
   ]]>
   </mx:Script>
   

   <mx:WebService id="testWS" useProxy="false"
      wsdl="http://myserver/cfc/RemoteObject.cfc?wsdl">...;
      <mx:operation name="getRemoteData"
      result="handleResult(event)"
      fault="handleFault(event)" />
   </mx:WebService>
      
   <mx:Button x="277" y="169" label="Run Web Server " click="testWS.getRemoteData()" width="235"/>

</mx:Application>
# Posted By Samer Sadek | 5/19/09 3:50 PM
Jason Dean's Gravatar @samer,

Thanks for looking into that. That is really good to know. I really need to get to learning Flex. It looks like such fun.
# Posted By Jason Dean | 5/19/09 9:38 PM
Craig M. Rosenblum's Gravatar Could we see some the source code for this, and would we be able to access your cfc remotely?

I am working on my 1st adobe air project, and it need's to send/receive data via xml to a wireless receiver connected to a desktop pc, which is nowhere near our web server.

But I have been battling to the jquery working, and to fix problems with the cross domain issue.

I can't do this with a coldfusion page, or a normal jquery page, since that isn't going to work with the cross domain blockage.

Any ideas or suggestions?
# Posted By Craig M. Rosenblum | 12/30/10 2:07 PM
Jason Dean's Gravatar Craig, there should be no cross-domain issues with Adobe AIR applications. AIR does not enforce the same cross-domain policy as the browser. You should have no troubles (in that way) with having an AIR application talking to a ColdFusion page on a different domain.

I'm sorry, I do not have the original source-code or the remote CFC, but I do have a sample application that does exactly what you are describing. It makes cross domain requests and gets back XML data ( I think, it might be JSON data ).

Anyway, you can download the sample app here: http://www.12robots.com/enclosures/shortstoriesapp...

I just spent an hour getting it up and running again, so I expect to hear how things go ;)

The app talks to remote CFCs on my domain using remote Ajax calls done with jquery. The Zip file contains all of the source code plus the ready-to-run AIR application.

Let me know how it goes.
# Posted By Jason Dean | 12/30/10 7:04 PM
Craig M. Rosenblum's Gravatar Thank you so much for the example, this is exactly what I have been looking for, to help me with my 1st adobe air project.

Thank You...

P.S. Happy New Year from a fellow Minnesotan :)
# Posted By Craig M. Rosenblum | 1/3/11 9:13 AM
Jason Dean's Gravatar w00t! Happy New Year. Let me know how it goes.
# Posted By Jason Dean | 1/3/11 10:02 AM
BlogCFC was created by Raymond Camden. This blog is running version 5.9.1. Contact Blog Owner