17 January 2008 ~ 21 Comments

URLRequestHeader in AS3 Can Not Use Authorization Header

Ok, so I had my first WTF moment last night in trying to be more AS3 and flash happy. I started the FreshBooks API AS3 Library, and I tested it in Flex 3 and AIR. It worked great. Just so that the FreshBooks folks would know I started the project, I hit their contact us form and let them know. I was reading the API docs the other day and was surprised to see that they had added my library to the list of projects. How Cool! The only rub was they labeled it as a Flash project. That got me wondering if I had used anything that would keep it from working in Flash.

I scanned the code and was very pleased to see that the only class that would be an issue was ArrayCollection. So I changed that up and made and array out of it. No Sweat. Everything compiles and I am a happy guy. So I run it to test it out.

ArgumentError: Error #2096: The HTTP request header Authorization cannot be set via ActionScript.

Wait, what?!?! I set it via actionscript in a flex project with no issues. How is this different? Well I dug a little deeper and here is the rub. In the livedocs for AS3 URLRequestHeader its specified that Authorization is a reserved word. But in the class docs for Flex 2 URLRequestHeader it is not. Although I thought last night when I was looking at this the Flex 3 livedocs for URLRequestHeader didnt list it, it apears to. The problem is, this code works in Flex and AIR, but not in an AS3 only project.

First question is why is it reserved in AS3 and not Flex. Second, why does it work in Flex 3 when it shouldn’t. Third, how they hell am I supposed to authenticate against remote services without this?

I appeal to the flash gods that are smarter than me. Please set me straight

21 Responses to “URLRequestHeader in AS3 Can Not Use Authorization Header”

  1. Ben 17 January 2008 at 12:40 pm Permalink

    Hi Simeon,

    My bad for listing Flash on the website; I blame my ActionScript ignorance :(

    - Ben

  2. Simeon 17 January 2008 at 12:56 pm Permalink

    Hey Ben,

    I wouldn’t say it was your bad at all. Your post made me think about if I could reach a larger audience with the lib.

    Now I want to know how its supposed to work without that header. i’ll find out more :) Cuz if the docs are right, my example shouldnt work at all.

    Thanks for the link BTW. Its really cool that you guys are so responsive. I hope fresh books does very well.

  3. David Brewer 17 January 2008 at 8:58 pm Permalink

    We’re struggling with this same question about the Authorization header being disallowed. From what I’ve seen on various forums, it seems that it used to work in earlier releases of Flash 9 but was added to the blocked list sometime relatively recently.

    I’m not sure exactly how one is meant to communicate with any kind of web service that uses HTTP Auth now. If you find a solution I’ll be very interested to hear about it.

  4. David Brewer 17 January 2008 at 9:59 pm Permalink

    Has anyone tried this library out that can report on how well it works?

    http://code.google.com/p/as3httpclientlib/

  5. Simeon 17 January 2008 at 10:23 pm Permalink

    I have not tried the lib, but I follow duck_typer’s blog. I think he is working on his own set of issues with flash before he can finish the library.

    I thought I would be smart tonight and just write a new class that extends the old one, but it doesnt seem to work. I wonder if URLRequestHeader is someone marked as final.

    I’ll keep digging.

  6. Simeon 17 January 2008 at 10:27 pm Permalink

    Of course if I had really read the docs I would have seen that it is final. So I can’t even fake it.

  7. Maxim Porges 20 January 2008 at 6:20 am Permalink

    One of my buddies and I battled with this a little bit on an app we’re working on, authorizing against a Rails REST API. He figured out a way to do authorization, although I can’t remember how.

    I’ll see if I can get him to post his findings.

    - max

  8. Simeon 20 January 2008 at 9:55 am Permalink

    Hey Max,

    I actually have this working right now, using flex. The problem is (as I have gleamed from harassing employees) that this is a change that occurred as part of the .115 flash player updates.

    And that moving forward the Authorization header will not be allowed. So now I am waiting to find out if there is a way to do this built in but not obviously. Or if we have to commit to helping the project listed above so our apps can continue to work.

  9. Joeri Sykora 25 January 2008 at 3:38 am Permalink

    Hello Simeon,

    I’m developing a Flex application that can manage a Blogger blog, which uses the Google Data API (http://code.google.com/apis/gdata/auth.html). However, to be able to add/edit/delete posts, I am required to set some value in the Authorization header on the request. Which of course doesn’t work, as you mention in your blog.

    From reading your last comment it seems you have found a workaround for this problem? Or do you perhaps no longer need the Authorization header in your API?

  10. Simeon 25 January 2008 at 7:08 am Permalink

    Hey Joeri,

    Actually not so much a work around as, it works in flex 2, and the beta of flex 3, but shouldn’t work when 3 gets released. It also doesn’t work in an AS3 only project in flex builder.

    So I am still working out how to get around this. I have an email to a couple folks at Adobe hoping to get some clarification.

  11. Simeon 26 January 2008 at 10:13 am Permalink

    Ryan Stewart pointed my to this technote which confirms “WHY” this doenst work.

    http://kb.adobe.com/selfservice/viewContent.do?externalId=kb403030&sliceId=2

    But the KB is not helpful in providing a work around or alternative solution.

  12. Simeon 26 January 2008 at 7:42 pm Permalink

    So it appears that the word from on high, is that this really has been disabled. The current work around is to use a different header name. This will only work if you also control the server you are connecting to.

    The other alternative is to implement another type of authentication for the API. Something like OAuth, or flickr’s token exchange might do.

    I’ll post back more if I sort something out. But I think this is closed for now.

  13. Simeon 28 January 2008 at 12:06 pm Permalink

    I have a new update for this posted here:

    http://blog.simb.net/2008/01/28/the-sky-is-falling-urlrequstheader-and-authorization/

    Problem is strictly related to Flash Player and does not affect the application security context of AIR applications.

    So if you target the browser you are still out of luck. However this functionality can still be utilized from within AIR.

  14. Danno 15 March 2008 at 12:30 pm Permalink

    I had a little AIR app working late last year that made a login request to google calendar api, got the seesion key and stuck it in the authentication header for subsequent interaction with the google calendar. Worked fine until Flex 3 arrived although it could be a Flash player issue. I used AIR in the first place to get around the browser cross domain issues that limited Flex browser apps.

    Now, even with AIR, and even for a POST method, I get the error:
    ArgumentError: Error #2096: The HTTP request header Authorization: cannot be set via ActionScript.

    Certainly, we need a means to access web apis needing authentication…google, yahoo etc. Has Adobe stated their position on this?

  15. Au Pair 18 March 2008 at 6:30 pm Permalink

    very nice web site. My English is not so good, so I do not understandt it well, but it seems very good. Thanks

  16. Phil 4 April 2008 at 2:19 am Permalink

    Hi,

    Did you guys find a workaround? Or news from Adobe?
    Phil

  17. Simeon 4 April 2008 at 6:18 am Permalink

    Hey Gang,

    While the issue is still a problem, Adobe recognized the issue and has provided a workaround in the April update to flash player. Please see this post for details.

    http://blog.simb.net/2008/03/18/april-flash-player-updates/

  18. H2Obrain 17 September 2008 at 1:04 am Permalink

    I got this working in a flash as3 project, programmed with Flex SDK 3.0.3 in FlashDevelop(.org).

    By it’s working, I mean it’s working under Windows, on Mac’s there’s still the :
    ArgumentError: Error #2096: Der HTTP-Anforderungs-Header Authorization kann nicht mit ActionScript festgelegt werden.
    (it’s a german version :))

    Fucking security..

  19. H2Obrain 17 September 2008 at 1:07 am Permalink

    Besides, according the Adobe Homepage, only Proxy-Authorization is not allowed, i don’t see the Authorization-head er on this homepage..
    (http://kb.adobe.com/selfservice/viewContent.do?externalId=kb403030&sliceId=2)

  20. ALARIK 13 March 2010 at 10:59 am Permalink

    I FOUND A WORK AROUND:
    -create the URLRequest object
    -ADD A FAKE VARIABLE (this is the trick)
    -SET POST METHOD (mandatory)
    -add auth request header
    -issue the load

    example:
    request = new URLRequest ( path );
    request.data = new URLVariables ( “fakeVar=fakeVal”);
    request.method = URLRequestMethod.POST;

    var up:String = “name:password”;
    var credentials:String = encode(up);
    var authHeader:URLRequestHeader = new URLRequestHeader(“Authorization”,”Basic ” + credentials);
    request.requestHeaders.push(authHeader);

    loader.load ( request );

  21. Jason 24 March 2010 at 10:31 am Permalink

    Suggested reading:
    Advanced ActionScript 3 with Design Patterns
    by Joey Lott and Danny Patterson
    Go to chapter 15 for a better and complete solution.

    My example code:
    private var xmlResults:XML = new URLLoader;
    private var urlLoader:URLLoader = new URLLoader();

    public function fErrorHandler(e:IOErrorEvent):void {
    trace(“xml failed!”);
    }

    //when the “loader” event object finishes the loading of the xml file, run other needed functions to process the data
    private function fLoaderCompleteHandler(event:Event):void {

    trace(“xml loaded!!”); //jwt testing
    var result2:XML = new XML(urlLoader.data); // loads the xml file data into the xml object
    xmlResults = result2; //have the global xml object equal the current data loaded xml object
    result2 = null; // dont need current xml object any more so erase it

    fParseXML(0); //process the first set of records from the xml object
    trace(“found xml” + xmlResults.toString());
    }

    public function fParseXML(intAddNum:Number):void{
    //create variables to store the record info
    //
    var envelope:XML = xmlResults; //XML(urlLoader.data);
    var soap:Namespace = envelope.namespace(“soap”);
    var responseN:Namespace = new Namespace(“http://www.domain.com/school/ServiceCollege”);
    var resultL:XMLList = envelope.soap::Body.responseN::HelloTestResponse.responseN::HelloTestResult;

    var strTest:String;
    //if only one response field will be return by the web service
    strTest = resultL;
    //do something like this if multiple response feilds will be returned
    //strTest = resultL.response::schoolName.toString();
    trace(“parsing:” + strTest);
    trace(“done loading:”);
    }

    public function fBeginRequest():void{
    var strXMLDataRequest:String
    var urlRequest:URLRequest = new URLRequest();
    urlRequest.contentType = “text/xml; charset=utf-8″;
    urlRequest.method = “POST”;
    urlRequest.url = “http://www.domain.com/school/serviceCollege.asmx”;
    var soapAction:URLRequestHeader = new URLRequestHeader(“SOAPAction”,”http://www.domain.com/school/ServiceCollege/HelloTest”);
    urlRequest.requestHeaders.push(soapAction);
    strXMLDataRequest = “<soap:Envelope xmlns:xsi=\”http://www.w3.org/2001/XMLSchema-instance\” xmlns:xsd=\”http://www.w3.org/2001/XMLSchema\” xmlns:soap=\”http://schemas.xmlsoap.org/soap/envelope/\”>”;
    strXMLDataRequest = strXMLDataRequest + “<soap:Body>”;
    strXMLDataRequest = strXMLDataRequest + “<HelloTest xmlns=\”http://www.domain.com/school/ServiceCollege\” />”;
    strXMLDataRequest = strXMLDataRequest + “</soap:Body>”;
    strXMLDataRequest = strXMLDataRequest + “</soap:Envelope>”;
    urlRequest.data = new XML(strXMLDataRequest);
    urlLoader.load(urlRequest);
    urlLoader.addEventListener(IOErrorEvent.IO_ERROR, fErrorHandler); //add the event to the “loader” object
    urlLoader.addEventListener(Event.COMPLETE, fLoaderCompleteHandler); //add the event to the “loader” object
    }

    Soap Request:
    <?xml version=”1.0″ encoding=”utf-8″?>
    <soap:Envelope xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance” xmlns:xsd=”http://www.w3.org/2001/XMLSchema” xmlns:soap=”http://schemas.xmlsoap.org/soap/envelope/”>
    <soap:Body>
    <HelloTest xmlns=”http://www.domain.com/school/ServiceCollege” />
    </soap:Body>
    </soap:Envelope>

    Soap Response:
    <?xml version=”1.0″ encoding=”utf-8″?>
    <soap:Envelope xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance” xmlns:xsd=”http://www.w3.org/2001/XMLSchema” xmlns:soap=”http://schemas.xmlsoap.org/soap/envelope/”>
    <soap:Body>
    <HelloTestResponse xmlns=”http://www.domain.com/school/ServiceCollege”>
    <HelloTestResult>string
    </HelloTestResponse>
    </soap:Body>
    </soap:Envelope>


Leave a Reply

PHVsPjxsaT48c3Ryb25nPndvb19hYm91dDwvc3Ryb25nPiAtIEhpISBNeSBuYW1lIGlzIFNpbWVvbiBCYXRlbWFuIGFuZCBJIGFtIGEgd2ViIGFwcGxpY2F0aW9uIGRldmVsb3BlciBzcGVjaWFsaXppbmcgaW4gdGhlIEFkb2JlIEZsYXNoIFBsYXRmb3JtLiAgSSBhbSBhbiBBZG9iZSBDb21tdW5pdHkgUHJvZmVzc2lvbmFsIGFuZCBhbiBBZG9iZSBDZXJ0aWZpZWQgVHJhaW5lciBmb3IgRmxleCBhbmQgQUlSLiAgSSBhbSBhbHNvIHRoZSBQcmluY2lwbGUgSW5zdGlnYXRvciBmb3IgUE5XIFJhaW4gTExDIGEgUklBIGNvbnN1bHRpbmcgYW5kIG1lbnRvcmluZyBjb21wYW55LjwvbGk+PGxpPjxzdHJvbmc+d29vX2Fkc19yb3RhdGU8L3N0cm9uZz4gLSB0cnVlPC9saT48bGk+PHN0cm9uZz53b29fYWRfaW1hZ2VfMTwvc3Ryb25nPiAtIGh0dHA6Ly93d3cud29vdGhlbWVzLmNvbS9hZHMvd29vdGhlbWVzLTEyNXgxMjUtMS5naWY8L2xpPjxsaT48c3Ryb25nPndvb19hZF9pbWFnZV8yPC9zdHJvbmc+IC0gaHR0cDovL3d3dy53b290aGVtZXMuY29tL2Fkcy93b290aGVtZXMtMTI1eDEyNS0yLmdpZjwvbGk+PGxpPjxzdHJvbmc+d29vX2FkX2ltYWdlXzM8L3N0cm9uZz4gLSBodHRwOi8vd3d3Lndvb3RoZW1lcy5jb20vYWRzL3dvb3RoZW1lcy0xMjV4MTI1LTMuZ2lmPC9saT48bGk+PHN0cm9uZz53b29fYWRfaW1hZ2VfNDwvc3Ryb25nPiAtIGh0dHA6Ly93d3cud29vdGhlbWVzLmNvbS9hZHMvd29vdGhlbWVzLTEyNXgxMjUtNC5naWY8L2xpPjxsaT48c3Ryb25nPndvb19hZF90b3A8L3N0cm9uZz4gLSBmYWxzZTwvbGk+PGxpPjxzdHJvbmc+d29vX2FkX3RvcF9hZHNlbnNlPC9zdHJvbmc+IC0gPC9saT48bGk+PHN0cm9uZz53b29fYWRfdG9wX2ltYWdlPC9zdHJvbmc+IC0gaHR0cDovL3d3dy53b290aGVtZXMuY29tL2Fkcy93b290aGVtZXMtNDY4eDYwLTIuZ2lmPC9saT48bGk+PHN0cm9uZz53b29fYWRfdG9wX3VybDwvc3Ryb25nPiAtIGh0dHA6Ly93d3cud29vdGhlbWVzLmNvbTwvbGk+PGxpPjxzdHJvbmc+d29vX2FkX3VybF8xPC9zdHJvbmc+IC0gaHR0cDovL3d3dy53b290aGVtZXMuY29tPC9saT48bGk+PHN0cm9uZz53b29fYWRfdXJsXzI8L3N0cm9uZz4gLSBodHRwOi8vd3d3Lndvb3RoZW1lcy5jb208L2xpPjxsaT48c3Ryb25nPndvb19hZF91cmxfMzwvc3Ryb25nPiAtIGh0dHA6Ly93d3cud29vdGhlbWVzLmNvbTwvbGk+PGxpPjxzdHJvbmc+d29vX2FkX3VybF80PC9zdHJvbmc+IC0gaHR0cDovL3d3dy53b290aGVtZXMuY29tPC9saT48bGk+PHN0cm9uZz53b29fYWx0X3N0eWxlc2hlZXQ8L3N0cm9uZz4gLSBraGFraS5jc3M8L2xpPjxsaT48c3Ryb25nPndvb19hdXRvX2ltZzwvc3Ryb25nPiAtIGZhbHNlPC9saT48bGk+PHN0cm9uZz53b29fY2F0X21lbnU8L3N0cm9uZz4gLSBmYWxzZTwvbGk+PGxpPjxzdHJvbmc+d29vX2NvbnRlbnRfYXJjaGl2ZXM8L3N0cm9uZz4gLSBmYWxzZTwvbGk+PGxpPjxzdHJvbmc+d29vX2NvbnRlbnRfaG9tZTwvc3Ryb25nPiAtIGZhbHNlPC9saT48bGk+PHN0cm9uZz53b29fY3VzdG9tX2Nzczwvc3Ryb25nPiAtIDwvbGk+PGxpPjxzdHJvbmc+d29vX2N1c3RvbV9mYXZpY29uPC9zdHJvbmc+IC0gPC9saT48bGk+PHN0cm9uZz53b29fZmFjZWJvb2s8L3N0cm9uZz4gLSBzaW1iYXRlbWFuPC9saT48bGk+PHN0cm9uZz53b29fZmVlZGJ1cm5lcl91cmw8L3N0cm9uZz4gLSA8L2xpPjxsaT48c3Ryb25nPndvb19mb290X2NhdF9tZW51PC9zdHJvbmc+IC0gZmFsc2U8L2xpPjxsaT48c3Ryb25nPndvb19mb290X25hdl9leGNsdWRlPC9zdHJvbmc+IC0gPC9saT48bGk+PHN0cm9uZz53b29fZ29vZ2xlX2FuYWx5dGljczwvc3Ryb25nPiAtIDxzY3JpcHQgdHlwZT1cInRleHQvamF2YXNjcmlwdFwiPg0KdmFyIGdhSnNIb3N0ID0gKChcImh0dHBzOlwiID09IGRvY3VtZW50LmxvY2F0aW9uLnByb3RvY29sKSA/IFwiaHR0cHM6Ly9zc2wuXCIgOiBcImh0dHA6Ly93d3cuXCIpOw0KZG9jdW1lbnQud3JpdGUodW5lc2NhcGUoXCIlM0NzY3JpcHQgc3JjPVwnXCIgKyBnYUpzSG9zdCArIFwiZ29vZ2xlLWFuYWx5dGljcy5jb20vZ2EuanNcJyB0eXBlPVwndGV4dC9qYXZhc2NyaXB0XCclM0UlM0Mvc2NyaXB0JTNFXCIpKTsNCjwvc2NyaXB0Pg0KPHNjcmlwdCB0eXBlPVwidGV4dC9qYXZhc2NyaXB0XCI+DQp0cnkgew0KdmFyIHBhZ2VUcmFja2VyID0gX2dhdC5fZ2V0VHJhY2tlcihcIlVBLTExMTUwNTYtNFwiKTsNCnBhZ2VUcmFja2VyLl90cmFja1BhZ2V2aWV3KCk7DQp9IGNhdGNoKGVycikge308L3NjcmlwdD4NCjwhLS0gUGl3aWsgLS0+DQo8c2NyaXB0IHR5cGU9XCJ0ZXh0L2phdmFzY3JpcHRcIj4NCnZhciBwa0Jhc2VVUkwgPSAoKFwiaHR0cHM6XCIgPT0gZG9jdW1lbnQubG9jYXRpb24ucHJvdG9jb2wpID8gXCJodHRwczovL3N0YXRzLnBud3JhaW4uY29tL1wiIDogXCJodHRwOi8vc3RhdHMucG53cmFpbi5jb20vXCIpOw0KZG9jdW1lbnQud3JpdGUodW5lc2NhcGUoXCIlM0NzY3JpcHQgc3JjPVwnXCIgKyBwa0Jhc2VVUkwgKyBcInBpd2lrLmpzXCcgdHlwZT1cJ3RleHQvamF2YXNjcmlwdFwnJTNFJTNDL3NjcmlwdCUzRVwiKSk7DQo8L3NjcmlwdD48c2NyaXB0IHR5cGU9XCJ0ZXh0L2phdmFzY3JpcHRcIj4NCnRyeSB7DQp2YXIgcGl3aWtUcmFja2VyID0gUGl3aWsuZ2V0VHJhY2tlcihwa0Jhc2VVUkwgKyBcInBpd2lrLnBocFwiLCAxKTsNCnBpd2lrVHJhY2tlci50cmFja1BhZ2VWaWV3KCk7DQpwaXdpa1RyYWNrZXIuZW5hYmxlTGlua1RyYWNraW5nKCk7DQp9IGNhdGNoKCBlcnIgKSB7fQ0KPC9zY3JpcHQ+PG5vc2NyaXB0PjxwPjxpbWcgc3JjPVwiaHR0cDovL3N0YXRzLnBud3JhaW4uY29tL3Bpd2lrLnBocD9pZHNpdGU9MVwiIHN0eWxlPVwiYm9yZGVyOjBcIiBhbHQ9XCJcIiAvPjwvcD48L25vc2NyaXB0Pg0KPCEtLSBFbmQgUGl3aWsgVGFnIC0tPjwvbGk+PGxpPjxzdHJvbmc+d29vX2xvZ288L3N0cm9uZz4gLSAvYXNzZXRzL2ltYWdlcy9iZWNhdXNlSVNhaWRTby5wbmc8L2xpPjxsaT48c3Ryb25nPndvb19tYW51YWw8L3N0cm9uZz4gLSBodHRwOi8vd3d3Lndvb3RoZW1lcy5jb20vc3VwcG9ydC90aGVtZS1kb2N1bWVudGF0aW9uL21haW5zdHJlYW08L2xpPjxsaT48c3Ryb25nPndvb19uYXZfZXhjbHVkZTwvc3Ryb25nPiAtIDwvbGk+PGxpPjxzdHJvbmc+d29vX3Byb2ZpbGU8L3N0cm9uZz4gLSBodHRwOi8vaTMueXRpbWcuY29tL3ZpL3I5YWRpTU5aNEY0L2RlZmF1bHQuanBnPC9saT48bGk+PHN0cm9uZz53b29fcmVzaXplPC9zdHJvbmc+IC0gdHJ1ZTwvbGk+PGxpPjxzdHJvbmc+d29vX3Nob3J0bmFtZTwvc3Ryb25nPiAtIHdvbzwvbGk+PGxpPjxzdHJvbmc+d29vX3RoZW1lbmFtZTwvc3Ryb25nPiAtIE1haW5zdHJlYW08L2xpPjxsaT48c3Ryb25nPndvb190aHVtYl9oZWlnaHQ8L3N0cm9uZz4gLSAxMDA8L2xpPjxsaT48c3Ryb25nPndvb190aHVtYl93aWR0aDwvc3Ryb25nPiAtIDEwMDwvbGk+PGxpPjxzdHJvbmc+d29vX3R3aXR0ZXI8L3N0cm9uZz4gLSBzaW1iYXRlbWFuPC9saT48L3VsPg==