Adobe AIR Flex 3 HTTP Basic Authentication

I am a week into Flex 3 development building an AIR app to test the new API for Teamwork Project Manager and thought I would share an issue with HTTP Basic Authentication that I ran into.

2009-08-09 22:10:00.0

Adobe AIR Flex 3 HTTP Basic Authentication

I am a week into Flex 3 development building an AIR app to test the new API for Teamwork Project Manager and thought I would share an issue with HTTP Basic Authentication that I ran into.

To be honest it has been itching away at me all day today and half of yesterday and I finally solved it.

What I am trying to do:

  • Connect to the Teamworkpm.net API
  • Pass my URL, Username and Password to be authenticated
  • Catch the HTTP Status code in the response
  • Catch any IO errors if the URL can't be found
  • Catch an authorization failure for the credentials passed.
  • Use the URLLoader class in Flex 3

Sounds easy doesn't it? Well, I got everything working fine and then hit a snag. If the credentials passed did not authenticate, then the ugly browser Login dialog appeared right in my beautiful AIR app. I tried everything and eventually even re-wrote the whole thing TWICE using 2 Google Code projects for AS3 HTTP Client calls.

How I did it

I decided to scrap it all and start again. This is how I got it working.

  1. I need to send the login credentials to the server but there was no native method to do this. You need to push an authorization header into the Request Header in base64
    • import mx.utils.Base64Encoder;
    • var loader:URLLoader = new URLLoader();
      var req:URLRequest = new URLRequest(cURL);
      var headerRequests:Array = new Array(1);
      req.method="get";

      var headerRequests:Array = new Array(1);
      var encoder64:Base64Encoder = new Base64Encoder();
      encoder64.encode(cUsername + ":" + cPassword);

      var credentials:String = encoder64.toString();
      headerRequests[0] = new URLRequestHeader("Authorization", "Basic " + credentials);
      req.requestHeaders = headerRequests;
  2. This solved the first issue and after running the app with valid credentials, everything worked fine. Now I needed to supress the ugly Dialog on invalid credentials.

    • You need to set the authenticate property of your request to false.

    • req.authenticate=false
  3. I need to get the status code back now and handle the exception thrown if the URL can not be loaded. This is very easy and all that's required is to add event handlers for the following events:

    • loader.addEventListener(HTTPStatusEvent.HTTP_RESPONSE_STATUS,onStatus);
      loader.addEventListener(Event.COMPLETE,onComplete);
      loader.addEventListener(IOErrorEvent.IO_ERROR,onError);

    • private function onStatus(event:HTTPStatusEvent):void {
      Alert.show(event.status.toString());
      }

      private function onComplete(event:Event):void {
      Alert.show(event.target.data);
      }

      private function onError(event:IOErrorEvent):void {
      Alert.show(event.text);
      }
    • Be aware that the event:HTTPStatusEvent is the first event handled and then the onComplete is handled.

I hope the above helps some people. Even though all I was missing was a simple property set, the Live Docs documentation was not very helpful and trying to figure out the way to accomplish the problem was difficult. I did manage to learn a heap loads of how the URLLoader, URLRequest and event handling works.

Add to your del.icio.us    DIGG This!    Technorati Cosmos Link    Post to Reddit    Add to your Furl    Add to Blinklist
Comments [9] - Leave a comment

Comments

If this is a strictly AIR app, have you considered using the static method URLRequestDefaults.setLoginCredentialsForHost(domain, password, username);

This method handles all sorts of authentication: Basic, Digest, Kerebos, ActiveDirectory. It is very useful.

Elsewhere in your code, you just make the HTTP request as if it required no authentication, and let the magic/unicorns happen.

Cheers,
Doug
Hi Doug, cheers for the comment!

Yeah, I saw that static method but I'm unsure how a failed authentication would be handled.

Have you any pointers?

Dan.
edm said:
hey daniel!!! if login credentials are wrong, u are being served a native login window. i use vista and my windows was this disgusting windowsLoginThingy.

peace
James said:
Hello Dan,

Good to see you posting again. I have checked back in on your blog off and on for about 3 months you write interesting stuff, hope you continue to do so on a more frequent basis :-).

Cheers,

JW
Max said:
Ah this is cool. Like it also helped you learn more about event handling, it helped me. Nice post.
Max said:
Ah this helps me learn a lot about event handling, as it did to you. Very nice and interesting post.
Pet said:
Good work. Thanks for letting us know.
Joost said:
A little off topic: can Air "read" the windows credentials, so you can make a Single Sign On app with air, that logs the user in, based on the windows login?
Doug Schmidt said:
In AIR 1.5, the closest you can get to reading the Windows credentials is to get the folder name of the user directory, and hope that they have a standard Win config. So that would be asking for File.userDirectory.name, which is a String.

In AIR 2.x, you could spawn a native OS process that extracts the actual credentials, but by adding native process calls, you will be forced to write a native app installer. Not a huge deal, but a bit of a pain.

Hope this helps.