Securing your Flex application with Spring Security and Active Directory
![]() Download Sample |
See also my follow up article: Securing your Flex app: smart card authentication with Spring Security
The goal of the current article is to provide a clear overview how to integrate a Flex application with Active Directory using the authentication and authorization mechanism offered by the new Spring Security.
Before downloading the sample project, you should have: Java web app server (I'm using Apache Tomcat) and Active Directory with login credentials. Instead of AD you can use any LDAP directory server (for example ApacheDS).
To run the sample Flex project you don't need download extra .jar or .swc libraries or create a Java project with an IDE. Just unzip the sample project into your Tomcat webapps directory and change LDAP server settings. However, to recompile the Flex project you should download the Flex source project with Granite DS library granite.swc, add it to the Flex Build Path and to define Flex Server. The directory structure for the project looks like.
For those who don't know: Spring is an lightweight Java framework. Spring Portfolio includes now the Spring Security 2.0. providing comprehensive security services for J2EE-based enterprise applications. Spring Security 2 builds upon the popular Acegi Security, but it is much easier to use than former Acegi Security. Rod Jonson, creator of the Spring framework, noticed recently that one of the problems with Acegi Security was that it was very powerful but it wasn't simple to use.
Version 2.0 of the Spring framework introduced namespace configuration. For example, it allows a more clearer way of configuring your LDAP server. To allow the security namespace in your application context just add the schema declaration to application context file:
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:s="http://www.springframework.org/schema/security" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-2.0.2.xsd"> </beans>
Before we go further, take a look to the UML sequence diagram. The diagram itself (as the slogan "Security is hard, let's use tools!) is taken from the presentation of Mike Wiesner Using Spring Security 2 (SpringOne'08). Treat the policewomen like a Security Interceptor.

Authentication
First, let's look at the web.xml that has a DelegatingFilterProxy. It maps all the requests to springSecurityFilterChain.
<filter> <filter-name>springSecurityFilterChain</filter-name> <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> </filter> <filter-mapping> <filter-name>springSecurityFilterChain</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
We can now edit our application context file /WEB-INF/conf/applicationContext-security.xml. The first thing we need to do is to configure the ldap-server element by providing the URL to our Active Directory server and a full DN for the manager we want use for lookups. Instead of definining the DN for the user (by replacing the user login name in the supplied pattern) we are configuring an LDAP search filter to locate the user. As Active Directory uses a different account object, we have to specify sAMAccountName for the UID object. Next we are loading authorities from groups in the LDAP directory using ldap-authentication-provider element and group-* attributes.
<s:ldap-server url="ldap://activedirectory:10389" manager-dn="CN=My Service Account,OU=Accounts, DC=mindtheflex, DC=com" manager-password="password" /> <s:ldap-authentication-provider user-search-base="OU=Accounts, DC=mindtheflex, DC=com" user-search-filter="sAMAccountName={0}" group-search-filter="member={0}" group-role-attribute="cn" group-search-base="OU=Groups, DC=mindtheflex, DC=com" role-prefix="ROLE_" />
Using ApacheDS, you can change ldap-server and ldap-authentication-provider configuration:
<s:ldap-server url="ldap://localhost:10389" manager-dn="uid=admin,ou=system" manager-password="secret" /> <s:ldap-authentication-provider user-dn-pattern="uid={0},ou=people" group-search-filter="uniqueMember={0}" group-role-attribute="cn" group-search-base="ou=groups,dc=example,dc=com" role-prefix="ROLE_" />
GraniteDS
Now, let's examine again the web.xml. I'm using Granite Data Services library for integrating my Flex application with J2EE application server. Granite DS (developed by Franck WOLFF) is a free, open source alternative to Adobe LiveCycle Data Services. See project home for more documentation. GraniteDS seems to me to be more "flexible" than Adobe LDS (now known as BlazeDS) for integrating rapidly Java community-driven features (Spring framework, hibernate etc). If you are interested how to hack BlazeDS and put it work with Spring Security 2.0, see the Igenko project (more links bellow) and Gridshore's blog.
GraniteDS uses AMF3 binary format for data serialization/deserialization and remote method invocation. We have to define AMFMessageServlet and url pattern. This servlet handles all requests matching the /graniteamf/* pattern and is pretty similar to BlazeDS MessageBrokerServlet. Both GraniteDS and BlazeDS are using binary remoting to convert data objects between your Java application on the back-end and AS3 in Flex.
<filter> <filter-name>AMFMessageFilter</filter-name> <filter-class> org.granite.messaging.webapp.AMFMessageFilter </filter-class> </filter> <filter-mapping> <filter-name>AMFMessageFilter</filter-name> <url-pattern>/graniteamf/*</url-pattern> </filter-mapping> <servlet> <servlet-name>AMFMessageServlet</servlet-name> <servlet-class> org.granite.messaging.webapp.AMFMessageServlet </servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>AMFMessageServlet</servlet-name> <url-pattern>/graniteamf/*</url-pattern> </servlet-mapping>
The next step is to configure your Spring destinations in /WEB-INF/flex/services-config.xml file:
<service id="granite-service" class="flex.messaging.services.RemotingService" messageTypes="flex.messaging.messages.RemotingMessage"> <destination id="login"> <channels> <channel ref="my-graniteamf" /> </channels> <properties> <factory>springFactory</factory> <source>loginService</source> </properties> <security> <security-constraint> <auth-method>Custom</auth-method> <roles> <role>ROLE_ADMIN</role> <role>ROLE_USER</role> </roles> </security-constraint> </security> </destination> </service> <channels> <channel-definition id="my-graniteamf" class="mx.messaging.channels.AMFChannel"> <endpoint uri="http://{server.name}:{server.port}/{context.root}/graniteamf/amf" class="flex.messaging.endpoints.AMFEndpoint"/> </channel-definition> </channels>
To enable Spring Security, you have to put a declaration in /WEB-INF/granite/granite-config.xml file:
<granite-config> <security type="org.granite.messaging.service.security.SpringSecurityService"/> </granite-config>
Flex application
My example is based on the GraniteDS demo, but I have simplified it considerably just to login into Active Directory and calling two method form Java — one for 'user' and another for 'admin'. Indeed, there is nothing complex here — but should it? One thing I'am going to say is that the new Spring Security with GraniteDS are great tools to make your life easier if you are building enterprise-level apps in Flex.


Login.mxml
<mx:Panel title="Login" xmlns:mx="http://www.adobe.com/2006/mxml"> <mx:Script> <![CDATA[ [Bindable] public var onCredentialsSet:Function = null; [Bindable] public var loginMessage:String = ""; [Bindable] public var loggedIn:Boolean = false; ]]> </mx:Script> <mx:Text text="(Type in user/user or admin/admin)" textAlign="center"/> <mx:Form> <mx:FormItem label="Username"> <mx:TextInput id="username"/> </mx:FormItem> <mx:FormItem label="Password"> <mx:TextInput id="password" displayAsPassword="true" enter="onCredentialsSet(username.text, password.text)"/> </mx:FormItem> </mx:Form> <mx:Text text="{loginMessage}" textAlign="center"/> <mx:Button label="Login" click="onCredentialsSet(username.text, password.text)"/> </mx:Panel>
Main.mxml
import org.granite.rpc.remoting.mxml.SecureRemoteObject; [Bindable] private var srv:SecureRemoteObject = null; ... public function onCredentialsSet(username:String, password:String):void { srv.setCredentials(username, password); }
Method authorization
Configuring the method level authorization you just have to define the secure methods either with pointcuts in the XML or with annotations in Java. The global-method-security element (in /WEB-INF/conf/applicationContext-security.xml) provides method security for all beans registered in the Spring application context. To restrict access to any method in the application you can enable annotation-based security and annotate secured method directly in Java code. If you are using Java 5 or greater, then more standard-compliant JSR-250 security annotations (@RolesAllowed( {"ROLE_ADMIN"} )) can be used as well.
package mypackage; import org.springframework.security.annotation.Secured; public class Login { @Secured({"ROLE_ADMIN"}) public String getAdminData() { return "Login.getAdminData()"; } @Secured({"ROLE_USERS"}) public String getUserData() { return "Login.getUserData()"; } }
But there is also another way that allows you to leave the Java code as it is and you can define a protected pointcut and the access control configuration attributes in XML. Using protect-pointcut allows you to apply security only with a simple declaration. The methods starting with getAdmin need the role ROLE_ADMIN. Every bean registered in the Spring application context that provides a method that matches the pointcut will have security authorization.
<s:global-method-security> <s:protect-pointcut expression="execution(* mypackage.Login.getAdmin*(..))" access="ROLE_ADMIN"/> </s:global-method-security>
You can even use XML to override method security metadata expressed by @Secured annotations, or @Secured annotations overriding method security metadata expressed by JSR 250 annotations. Note that using a protected pointcut the other dependent jars *.jar files (Aspectj and CGLIB2) are required.
You can propagate Spring Security exeptions to Flex:
public function onSecurityEvent(event:SecurityEvent):void { switch (event.type) { case SecurityEvent.INVALID_CREDENTIALS: loginView.loginMessage = "Invalid username or password"; loginView.loggedIn = false; break; case SecurityEvent.NOT_LOGGED_IN: srv.logout(); loginView.loginMessage = ""; loginView.loggedIn = false; break; case SecurityEvent.ACCESS_DENIED: Alert.show("You don't have required rights to execute this action\n"+event); break; } }

Flex and Active Directory Sample Project
Download sample project.
Anyone else who is interested to look at the source code can download it here.
External links:
Igenko:
http://code.google.com/p/igenko/wiki/FlexDataServices
http://tech.groups.yahoo.com/group/graniteds/message/1374
BlazeDS and Spring Security
http://www.machine501.com/blog/2008/02/14/blazeds-and-spring-security/
http://www.machine501.com/blog/2008/05/30/blazeds-spring-and-acegi-security-part-2/
http://www.machine501.com/blog/2008/06/01/blazeds-and-springacegi-security-part/
BlazeDS and Spring/Acegi integration
Acegi LoginCommand for FDS
Integrating flex 3 with spring security (formerly known as Acegi)
Granite with ACEGI

July 8th, 2008 at 1:10 am
[…] Securing your Flex application with Spring Security and Active… Before downloading the sample project, you should have: Java web app server (I’m using Apache Tomcat) and Active Directory with… […]
July 14th, 2008 at 4:00 pm
[…] and integrate authentication and authorization with spring security. A few days a go I received a trackback from sven. Curious as I am I started reading the material he provided and especially the other links he […]
November 11th, 2008 at 6:43 am
[…] Securing your Flex application with Spring Security and Active Directory […]
December 12th, 2008 at 2:06 am
hey so, i have the example you wrote up almost working, Thanks for taking the time to publish it, its really neat, however i am banging my head against one really (trivial thing im guessing)
when i direct this to my company ldap i get:
[LDAP: error code 48 - Inappropriate Authentication]; nested exception is javax
.naming.AuthenticationNotSupportedException: [LDAP: error code 48 - Inappropriat
e Authentication]
I feel like I need to somehow add a password encoder sha, but not certain where one can do that?
here is my config
December 14th, 2008 at 10:30 pm
[…] - bookmarked by 3 members originally found by sanyaissues on 2008-11-11 Securing your Flex application with Spring Security and Active… http://www.mindtheflex.com/?p=67 - bookmarked by 3 members originally found by HotPinkMidNite on […]
December 21st, 2008 at 11:12 pm
Great article, but one note, if I may:
when using annotation for method security, you forgot to mention that we need to declare in on our application security context. like so:
other wise it won’t work :).
January 7th, 2009 at 1:14 pm
well, i have done the same thing without ldap, but with the login/pass stored in the spring file.
and when i enter good login/pass, it works,
when i enter wrong login/pass, i’ve got rejected => this is what i want,
but if i re-enter good login/pass, i’ve got rejected too !
the only solution i’ve found is to reload the current page.
any idea ?
March 26th, 2009 at 4:24 pm
[…] In this article I am going to show you how to implement Smart Card authentication mechanism in a Flex application with Spring Security. I will use X.509 certificate authentication and database authorization simultaneously. To get a full picture of the topic, you should take a look at my previous article Securing your Flex application with Spring Security and Active Directory. […]
April 27th, 2009 at 11:59 pm
did you use comic life for that UML sequence diagram? really nice, actually
August 5th, 2009 at 10:44 pm
Great article, thanks,
By the way, what tool did you use for your UML sequence diagram (http://blog.mindtheflex.com/wp-content/uploads/2008/07/uml.png)?
it looks great !!
August 5th, 2009 at 11:26 pm
Comic Life, it’s better than Visio :))
September 11th, 2009 at 12:49 am
Hi! I was surfing and found your blog post… nice! I love your blog.
Cheers! Sandra. R.
January 4th, 2010 at 2:32 am
hi sven
i have trouble, i can’t send the value and this details
“Fault: Client.Error.MessageSend - Send failed”
can you help me….
thx