Donnerstag, 27. Oktober 2011

Using css in a Flex Library Project

Tested with Flash Builder 4.5.1

To make it work with Flash Builder:
  • File must be named defaults.css (not default.css!)
  • Must be checked as "Asset" in the Flex Library Build Path (Flash Builder)

  • For ant

    Note: the file defaults.css should be directly in root of your source-folder (might be "src").
     
       
         
         
         
       
     
    
    For further information: http://livedocs.adobe.com/flex/3/html/help.html?content=compilers_22.html

    Example for css and usage

    Note: You do not need to import the defualts.css in any of your library-mxml-files because the defaults.css is used as default as the name already says.
    
    defaults.css
    @namespace s "library://ns.adobe.com/flex/spark";
    @namespace mx "library://ns.adobe.com/flex/mx";
    
    .userDataFormStyle s|FormItem
    {
    skinClass : ClassReference("spark.skins.spark.StackedFormItemSkin");
    }
    
    The style will be applied to:
    
    
    
    
    
    
    
    
    

    Montag, 17. Oktober 2011

    Chaining your ant build files - common build problems


    This is a small collection of problems that might appear for the first time, when you start to chain your build files to build up the magic button: build all projects and create deployable.

    Example how to build the top-level-chain:
    
     
     
       
      Calling ant build for client module core... 
      
      
      ...
      
      Calling ant build for the client application... 
      
      
      Calling ant build for the server... 
      
      
     
    
    
    


    Heap space problems

    Error:
    Not enought heap space
        [mxmlc] Fehler: Java heap space

    Solution:
    Add the jvmargs for heap adjustment to the mxmlc-Task and set fork to true. Example:
    <mxmlc ...="" fork="yes" jvmargs="-Xms512m -Xmx512m">




    Accidently forked?
    Error:
    BUILD FAILED
    java.io.IOException: Cannot run program "javac.exe"
    ...
    ... build.xml:41: Error running javac.exe compiler
    ... org.apache.tools.ant.ProjectHelper.addLocationToBuildException(ProjectHelper.java:508)

    Solution
    <javac ...="" fork="false">


    Forgot to fork?
    Error:
    ...\build.xml:13: compc task failed
    Solution:
    <compc ...="" fork="yes">

    Problems with flex-config.xml
    Error:
    [mxmlc] command line: Fehler: „flex-config.xml“ konnte nicht geöffnet werden
    ...\build.xml:47: mxmlc task failed
    Solution:
    <mxmlc ...="" fork="yes"></mxmlc></compc></javac></mxmlc>




    Dienstag, 4. Oktober 2011

    Building Flex library projects with ant

    Building flex lib projects with ant is very easy. To make it even easier just use the following as template...

    Tested with: Flex 4.5 and ant 1.7 within the Eclipse IDE (3.6)
    
    
     
    
     
    
    
     
     
     
    
       
         
           
            
           
         
       
      
       
          
       
    
     
      
     
      
        
    
    
    

    ActionScript HTTPService - a common error - Error #1090

    If your application is quite fine but someday you get an error like this: Error #1090: XML parser failure: element is malformed
    Then you might have just missed to explicitly set the resultformat to something different than the default which is xml in Flex 4.5.

    So the snippet with the fix in the last line is:
    var service: HTTPService = new HTTPService();
    service.url = url;
    // note: default seems to be xml. XML seems to work for most cases but crashes for exmaple if a json response contains the character '<'
    service.resultFormat = "text";
    
    
    

    For the folks that thought as I did for the first time - here a short reminder: Flex does not care about the correctly set response type of your reponse. You have to set it manually as seen above.

    Sonntag, 28. August 2011

    Flash/Flex: Using Browser-Based Challenge-Response-Mechanisms for easy front-end to back-end communication

    You have an application that needs authorization and you don't want to encode the credentials in the URL for each request. So why not delegate the authorization-stuff to the browser, your flash application is running in?
    That article will show you one way to do that. It will also show up some pitfalls and important things to keep in mind.

    Discussion

    Is it better to transmit the credentials encoded in the URL or in the headers of the request being sent? Whats the advantage of browser based authentication instead of URL-encoded credentials?

    So, first of all everybody of us should get the bad smell, if one wants to add credentials as part of the query-string of an URL. But why is it bad?

    If you have no session that is checked for every request (which is normally true for REST-Applications and a lot of other scenarios) then anyone might copy and paste a URL-request into the address bar of a browser and you will receive the requested data without further authorization - sure, you have encoded the credentials in the URL itself... That might be very useful for testing and might ease your development. But the browser chronic and history might be a very interesting thing for malware that might cross your computer.
    Ok, the proceeding point might not matter in a typical scenario. That is because the requests you are sending through the flash player will never leave the flash-player in a way that they might end up in the history.
    But what if you someday want to interact with your browser in a different way: Maybe you want to request a resource that only authorized users should have access to. But you don't want that resource to be handled by the browser, instead of the flash player. One such scenario could be the desire to directly download and open a file with the default application that is set for that file type in the browser (Word or Excel for example).
    How could that be achieved? You can easily add a hidden iframe to the embedding website and use JavaScript to re-point the src of the iframe to the resource (see http://hohenbichler.blogspot.com/2011/08/flashflex-load-resources-due-browser.html). The result will be the standard file-download-dialog of the browser and if the user wants so, the dialog is skipped and the file is directly opened with the correct application.
    That is the point where you might get into trouble with the URL-encoded credentials: The URL is now leaving the flash-player and it is hold in JavaScript. That still might be no big issue. But maybe the associated program is saving the source-URL from where the file was get, or the download-history of your browser is saving the URL just for convenience as it always does (in Firefox right click on a downloaded file and choose copy download location). That might be a big security whole and your carefully setup https-connection is absolutely useless. It could get even worse: What if you are not absolutely ware of what you are logging on the server: Maybe you are running logging on info-level and that includes the requested URL for every request? For that case your highly secure LDAP-environment or your carefully salted user-credentials-db is absolutely useless because your logs contain all credentials of all your active users - What a mistake!

    Now a technical reminder at that place: Also if you only see sth. like auth=32897shduiw= in your URL as part of the query-string, that is typically no encrypted user name and password. Most the time that is only a base-64 encoded string that could be decoded by everyone to clear-text user name + password. So encoded is not encrypted!


    One way to use browser based authentication

    At first we should clear our goals

  • We want a log-in dialog that works perfectly and is part of flash application.

  • We don't want an ugly browser-based authentication dialog.
    We don't want the credentials to be part of the URL and we want to prevent every situation where credentials could leak in into logs or some kind of client-sided history.

  • We want to have the option to request resources from our flex-application that should be handled by the browser.

  • we don't want to modify request-headers by ourselves.


  • Short illustration: Credentials in the headers (firebug)







    The solution

  • A flash-based log-in dialog that takes over the credentials (user name + password).




  • A simple JavaScript function that builds up a XMLHTTPRequest, takes user name + password and is blocking until the response arrives.




  • The flash/flex-application is checking the result of the JavaScript/browser based authentication and either shows up a "invalid credentials" message or logs the user in.




  • li>After the browser-based authentication is done, our application can forget about everything that has to do with authentication. The browser will transparently add the credentials to the http-request-headers every time.





    The interesting part: Code

    The JS-Part
    
    

    The AS-Part
    //note: the onAuthSuccess function will change the application-state to logged-in and the handleAuthError will get a error-string and display the message to the user
    private function doChallengeResponseAuthentication(onAuthSuccess:Function, handleAuthError:Function):void{
    	
    	if (!ExternalInterface.available){
    		throw new Error();
    	}
    	
    	// note: the request we are sending is synchronous, so we need no callback-stuff that might complicate the javascript-actionscript-interaction
    ExternalInterface.call("authenticate", user, password);
    		
    	const loginResponseStatus:String = ExternalInterface.call("getResponseStatus");
    	const loginResponseText:String = ExternalInterface.call("getResponseText");
    	trace("loginResponseStatus: " + loginResponseStatus);
    	trace("loginResponseText: " + loginResponseText);	
    	
    	if(loginResponseStatus == "" || loginResponseText == "" ){
    		throw new Error("Unable to read login response data from JS");
    	}			
    	
    	if(loginResponseStatus == "200"){
    		// our login also returns some JSON data that we decode here
    		onAuthSuccess(JSON.decode(loginResponseText));
    	} else if(loginResponseStatus == "403"){
    		handleAuthError("Login incorrect");
    	} else if(loginResponseStatus == "12029"){
    		handleAuthError("Server does not respond");
    	} else {
    		handleAuthError("Error: " + loginResponseStatus + " " + loginResponseStatus);
    	}
    	
    }
    


    Disable Rechellangeing

    You might need to change your server code to not re-challenge for the case of invalid credentials. If you don't do that you will get the ugly browser-based authentication popup in additon to you beautiful flash log-in dialog.

    If you are using restlet on server side you can disable re-challenging that way:

    ChallengeAuthenticator challengeGuard = new ChallengeAuthenticator(getContext(), ChallengeScheme.HTTP_BASIC, "Sample Service");
    challengeGuard.setVerifier(new CustomSecretVeryfier());
    challengeGuard.setRechallenging(false);
    


    Keep in mind

  • The most important thing is that our application still is "sniffable". Thatn means a bad guy that listens on our wire can capture all network-packages and extract the cretedntails - no matter if they are clear-text or base-64-encoded. That means you should really setup https if you have not done that, yet!




  • There is no common log-out function offered by the browser-APIs (only IE offers sth: document.execCommand("ClearAuthenticationCache");). The only cross-browser working way is to send invalid credentials and so destroy the current challenge-response-context.




  • Compared with URL-encoded credentials, one looses the ability to log in with different users multiple times in the same browser. That is because a browser only allows one open challenge-response-context.






  • Pitfalls

    I can't see the Authorization-Headers in my Debugging-/Networking perspective of the Internet Explorer


    Then you you should just open up Firefox and try firebug. Thats because IE just does not display that headers as you can see in the screenshots below:






    Getting JavaScript variables form the browser into your flex-application

    Here are big differences between the browsers:

    In Firefox (tested with FF6 and FF5): you can get whole complex JavaScript Objects form actionscript code. In other words you can ask for AuthContainer and you then could access all its properties over that. That does not sound interesting? Keep on reading and see how the IE works :-/
    In IE (tested with IE9): you could only get leaves of Objects. In other words: you can only get the property logged in of the Object AuthContainer. You cannot get the whole AuthContainer with all its properties. That makes programming a bit more ugly.

    So: You better write code on a common base and always use the ugly IE-way...



    Why use JavaScript for that? - I will modify the headers myself!

    You might think: Why not easily add the credential-stuff to each request I send through flash. That way I need no JavaScript interaction and the option to load resources directly through the browser is not relevant for me. If you are a flex expert than you might already know that flex does only allow header-modification on certain circumstances. The first obstacle is that get-request could not have user-modified headers - the flash-player will silently remove all changes. But you might have heard of a HTTP-Override-Header (TODO:Link to next Blog-Post) that needs server-sided support, but makes it possible to modify the headers of your http-requests. With that you really could get a working solution - just write the credentials in the right header-place and your server-code will see non difference to the chellenge-response made with XMLHTTPRequest. The problem that might appear later on is the following: When you combine browser-based authentication (automatically added credentials for each request by the browser) with the manually added http-header-credentials you will observe different behaviours in the different browsers. Today (August 2011) the following happens in IE8 and IE9: The credentials that you manually added to the request-headers are silently overwritten by the browser. In Firefox 6 you will get the following: The authorization-headers are appended (credentials are doubled under the same header key) and not replaced - that will mess up your authentication and your application is not usable any more. If you are running in IE. So in firefox you will immediately see a malbehaviour. But in the IE it could get even worse: Maybe you want use the cool "open directly with the correct application feature" only in some special part of your application. So thats the place wehere you implement the JavaScript-browser-authentication described above. If you do that you will get a mess: If you hit the reload-button of your browser and for that reason get a reloaded application with a showing up log-in dialog, you could login and everything seems to be fine. But, if you enter invalid credentials you will also be logged in - What the heck is happening? You are adding the wrong credentials manually to the headers but the browser is silently overwriting them with the still valid challenge-response, you have issued the last time you used the XMLHTTPRequest for authentication.
    So a final line-up: Never add credentials to headers by your own - It requires ugly workarounds to get it run and it might mess up your whole authentication-system and you will not immediately see that.