Friday, August 15, 2008

Securing a Grails application with Acegi and Crowd (Revisited)

I recently had a need to combine these technologies to provide authentication and authorization with Crowd in my Grails application. I ran across a very good article that handholds you through this process. You can reference the original aricle here.

However, I ran into several issue when I tried to apply the configuration in the article. The original article uses Grails 1.0.1, the Acegi Security Plugin v0.2, and Crowd 1.3. When I attempted to follow the instructions I attempted to use Grails 1.0.3, the Acegi Security Plugin v0.3, and Crowd 1.4. If you are still reading then make sure that you continue to use 0.2.1 version of the plugin because the Crowd integration module has not been updated to reference the latest Acegi/Spring Security framework updates such as pack naming. From here I will reference where you will need to make modifications for each step that requires it in the original article.

Step 1: Grails & Acegi Installation

Again, use the Acegi Security Plugin v0.2.1

Step 2: Create Grails Application with Acegi Security

Download and install the Acegi Security Plugin v0.2.1 in your Grails project.

Step 3: Crowd Download

Download Crowd v.1.4.4 from the Atlassian website.

Step 4: Crowd Installation & Configuration

The installation and configuration is surprisingly as easy as the original author suggests. Just follow the installation instructions.

Step 5: Grails + Acegi + Crowd Integration

Make absolutely sure that you do not skip the step regarding crowd.properties. If the application name and password do not match the same values in the application configuration you will not be allowed to attempt authentication against Crowd. You can setup these values in the Crowd administration console by navigating to the Applications tab and selecting the application from the list. From there click the Details tab and ensure the name and password are set to the same values as crowd.properties. Also, make sure that the application.login.url value is modified to the correct login url. The one specified in the article should be consistent with the example.

I did follow the author's lead and copied the applicationContext-CrowdClient.xml file from the
CROWD_HOME/client/crowd-integration-client-1.4.4.jar file and positioned it in the ACEGI_APP/conf/spring/ directory and then renamed the file to resources.xml.

The modifications I had to make to resources.xml were different from the author's article. Here are the beans I added:

   1  <bean id="crowdUserDetailsService" class="com.atlassian.crowd.integration.acegi.user.CrowdUserDetailsServiceImpl">
2 <property name="authenticationManager" ref="crowdAuthenticationManager"/>
3 <property name="groupMembershipManager" ref="crowdGroupMembershipManager"/>
4 <property name="userManager" ref="crowdUserManager"/>
5 <!--<property name="authorityPrefix" value="ROLE_"/>-->
6 <property name="authorityPrefix" value=""/>
7 </bean>
8
9 <bean id="crowdAuthenticationProvider" class="com.atlassian.crowd.integration.acegi.CrowdAuthenticationProvider">
10 <property name="userDetailsService" ref="crowdUserDetailsService"/>
11 <property name="authenticationManager" ref="crowdAuthenticationManager"/>
12 <property name="httpAuthenticator" ref="httpAuthenticator"/>
13 </bean>
14
15 <bean id="crowdLogoutHandler" class="com.atlassian.crowd.integration.acegi.CrowdLogoutHandler">
16 <property name="httpAuthenticator" ref="httpAuthenticator"/>
17 </bean>
18
19 <bean id="logoutFilter" class="org.acegisecurity.ui.logout.LogoutFilter">
20 <constructor-arg value="/"/>
21 <constructor-arg>
22 <list>
23 <ref bean="crowdLogoutHandler"/>
24 <bean class="org.acegisecurity.ui.logout.SecurityContextLogoutHandler"/>
25 </list>
26 </constructor-arg>
27 <property name="filterProcessesUrl" value="/j_acegi_logout"/>
28 </bean>
29
30 <bean id="filterChainProxy" class="org.acegisecurity.util.FilterChainProxy">
31 <property name="filterInvocationDefinitionSource">
32 <value>
33 CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
34 PATTERN_TYPE_APACHE_ANT
35 /images/**=#NONE#
36 /scripts/**=#NONE#
37 /styles/**=#NONE#
38 /**=httpSessionContextIntegrationFilter,logoutFilter,authenticationProcessingFilter,securityContextHolderAwareRequestFilter,rememberMeProcessingFilter,anonymousProcessingFilter,exceptionTranslationFilter,filterInvocationInterceptor
39 </value>
40 </property>
41 </bean>

AcegiGrailsPlugin.groovy


Instead of making this modification to this file I put the change inside of resources.xml. If you make this modificaiton inside the plugin code and you upgrade it you will need to remember this. Instead Grails will override the authenticationManager in AcegiGrailsPlugin with this definition inside of resources.xml:

   1      <bean id="authenticationManager" class="org.acegisecurity.providers.ProviderManager">
2 <property name="providers">
3 <list>
4 <ref local="crowdAuthenticationProvider"/>
5 <ref bean="anonymousAuthenticationProvider"/>
6 <ref bean="rememberMeAuthenticationProvider"/>
7 </list>
8 </property>
9 </bean>