SSO CAS Rocks with Acegi

Single Sign On CAS Acegi Configuration

Overview:

taking the definition from Acegi Documentation

CAS is an enterprise-wide single sign on system. Unlike other initiatives, Central Authentication
Service is open source, widely used, simple to understand, platform
independent, and supports proxy capabilities. Acegi Security fully
supports CAS, and provides an easy migration path from
single-application deployments of Acegi Security through to
multiple-application deployments secured by an enterprise-wide CAS
server.

Configuration:

  1. Download acegi-security-1.0.1.zip
  2. Download cas-server-3.0.4.zip
  3. Download tomcat-5.5

Hint: Here I'm using Tomcat as server that will only host the cas web application, my service applications will be on oc4j.

First, install the CAS application.

  as mentioned in Acegi documentation

CAS Version 3.0 Configuration

To install, you will need to download and extract the CAS
server archive. We used version 3.0.4. There will be a
/webapp directory in the root of the deployment.
Edit the an deployerConfigContext.xml so that it
contains your AuthenticationManager as well as
the CasAuthenticationHandler. A sample
applicationContext.xml is included below:

Code:
        <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC  "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
	<bean id="authenticationManager"
	      class="org.jasig.cas.authentication.AuthenticationManagerImpl">
		<property name="credentialsToPrincipalResolvers">
			<list>
				<bean class="org.jasig.cas.authentication.principal.UsernamePasswordCredentialsToPrincipalResolver" />
				<bean class="org.jasig.cas.authentication.principal.HttpBasedServiceCredentialsToPrincipalResolver" />
			</list>
		</property>

		<property name="authenticationHandlers">
			<list>
				<!--bean class="org.jasig.cas.authentication.handler.support.HttpBasedServiceCredentialsAuthenticationHandler" />
				<bean class="org.acegisecurity.adapters.cas3.CasAuthenticationHandler">
					<property name="authenticationManager" ref="acegiAuthenticationManager" />
				</bean-->

				<bean id="SearchModeSearchDatabaseAuthenticationHandler"
				      class="org.jasig.cas.adaptors.jdbc.SearchModeSearchDatabaseAuthenticationHandler"
				      abstract="false" singleton="true" lazy-init="default" autowire="default" dependency-check="default">
					<property name="tableUsers">
						<value>SF_INF_USERS</value>
					</property>
					<property name="fieldUser">
						<value>NAME</value>
				  	</property>
				  	<property name="fieldPassword">
				   		<value>PSWD</value>
				  	</property>
				  	<property name="dataSource" ref="dataSource" />
				</bean>
			</list>
		</property>
	</bean>


	<!--bean id="inMemoryDaoImpl" class="org.acegisecurity.userdetails.memory.InMemoryDaoImpl">
		<property name="userMap">
			<value>
				aabdelaziz=aabdelaziz,EPS_SYSTEM_ADMIN
				marissa=koala,ROLES_IGNORED_BY_CAS
				dianne=emu,ROLES_IGNORED_BY_CAS
				scott=wombat,ROLES_IGNORED_BY_CAS
				peter=opal,disabled,ROLES_IGNORED_BY_CAS
			</value>
		</property>
	</bean>

	<bean id="daoAuthenticationProvider" class="org.acegisecurity.providers.dao.DaoAuthenticationProvider">
		<property name="userDetailsService"><ref bean="inMemoryDaoImpl"/></property>
	</bean>

	<bean id="acegiAuthenticationManager" class="org.acegisecurity.providers.ProviderManager">
		<property name="providers">
			<list>
				<ref bean="daoAuthenticationProvider"/>
			</list>
		</property>
	</bean-->
		
	<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
		<property name="driverClassName">
			<value>oracle.jdbc.driver.OracleDriver</value>
		</property>
		<property name="url">
			<value>jdbc:oracle:thin:@10.1.119.76:1521:epsdb</value>
		</property>
		<property name="username">
			<value>eps</value>
		</property>
		<property name="password">
			<value>eps</value>
		</property>
	</bean>
</beans>

Note the granted authorities are ignored by CAS because it has
no way of communicating the granted authorities to calling
applications. CAS is only concerned with username and passwords (and
the enabled/disabled status).

Copy acegi-security.jar and
acegi-security-cas.jar files into
/localPlugins/lib. Now use the ant
war
task in the build.xml in the
/localPlugins directory. This will create
/localPlugins/target/cas.war, which is ready for
deployment to your servlet container.

Note CAS heavily relies on HTTPS. You can't even test the
system without an HTTPS certificate. Whilst you should refer to your
web container's documentation on setting up HTTPS, if you need some
additional help or a test certificate you might like to check the
CAS documentation on setting up SSL:
http://www.ja-sig.org/products/cas/server/ssl/index.html

 Deploy the generate cas.war to $CATALINA_HOME/webapp/

Configuration of CAS Client

you can read and get more details about each bean from Acegi Documentation - Chapter 18. CAS Authentication

here I will just past my applicationContext-acegiSecurity.xml, web.xml as it may be useful for some one like me who suffered before making it works.

­applicationContext-acegiSecurity.xml

Code:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">

<beans>
    <!-- UserDetailsService is the most commonly frequently Acegi Security interface implemented by end users -->
    <bean id="userDetailsService" class="ae.dxbpolice.eps.business.service.UserDetailsServiceImpl"/>

    <!-- This bean is optional; it isn't used by any other bean as it only listens and logs -->
    <bean id="loggerListener" class="org.acegisecurity.event.authentication.LoggerListener"/>
    
    <bean id="filterChainProxy" class="org.acegisecurity.util.FilterChainProxy">
        <property name="filterInvocationDefinitionSource">
            <value>
                CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
                PATTERN_TYPE_APACHE_ANT
                /**=httpSessionContextIntegrationFilter,logoutFilter,casProcessingFilter,exceptionTranslationFilter,filterInvocationInterceptor
            </value>
        </property>
    </bean>
    
    <bean id="httpSessionContextIntegrationFilter" class="org.acegisecurity.context.HttpSessionContextIntegrationFilter"/>
    
    <bean id="logoutFilter" class="org.acegisecurity.ui.logout.LogoutFilter">
        <constructor-arg value="/index.jsp"/><!-- URL redirected to after logout -->
        <constructor-arg>
            <list>
                <bean class="org.acegisecurity.ui.logout.SecurityContextLogoutHandler"/>
            </list>
        </constructor-arg>
    </bean>
    
    <!-- Authorization in Acegi Security is performed mainly by the FilterSecurityInterceptor filter. 
         This filter identifies a user-role relationship for a URL. 
          -->
    <bean id="filterInvocationInterceptor" class="org.acegisecurity.intercept.web.FilterSecurityInterceptor">
        <property name="authenticationManager" ref="authenticationManager"/>
        <property name="accessDecisionManager">
             <!-- The AffirmativeBased voter allows access if at least one voter votes
                  to grant access. Use the UnanimousBased voter if you only want to
                  grant access if no voter votes to deny access. -->
            <bean class="org.acegisecurity.vote.AffirmativeBased">
                <property name="allowIfAllAbstainDecisions" value="false"/>
                
                <property name="decisionVoters">
                    <list>
                        <bean class="org.acegisecurity.vote.RoleVoter">
                            <!--  Reset the role prefix to "EPS_", default is ROLE_ -->
                            <property name="rolePrefix">
                                <value>EPS_</value>
                            </property>
                        </bean>
                        <!-- The authenticated voter grant access if e.g.
                             IS_AUTHENTICATED_FULLY is an attribute -->
                        <bean class="org.acegisecurity.vote.AuthenticatedVoter" />
                    </list>
                </property>
            </bean>
        </property>
        
        <!-- Start the Dinamic URL-ROLe Mapping -->
        <property name="objectDefinitionSource">
            <ref local="dbDrivenFilterInvocationDefinitionSource" />
        </property>
    </bean>     
    
    <bean id="dbDrivenFilterInvocationDefinitionSource"
          class="ae.dxbpolice.eps.business.service.DatabaseDrivenFilterInvocationDefinitionSource">
        <property name="securityService">
            <ref bean="securityService" />
        </property>
    </bean>
    
    <bean id="rememberMeServices" class="org.acegisecurity.ui.rememberme.TokenBasedRememberMeServices">
        <property name="userDetailsService" ref="userDetailsService"/>
        <property name="key" value="changeThis"/>
    </bean>
    <!-- End Acegi Configuration for web -->
    
    <!-- ===================== Start of CAS SECURITY CONFIGURATIOS ==================== -->
    <bean id="serviceProperties" class="org.acegisecurity.ui.cas.ServiceProperties">
		<property name="service"><value>http://localhost:8889/eps/j_acegi_cas_security_check</value></property>		
		<property name="sendRenew"><value>false</value></property>
	</bean>

	<bean id="casProcessingFilter" class="org.acegisecurity.ui.cas.CasProcessingFilter">
		<property name="authenticationManager"><ref bean="authenticationManager"/></property>
		<property name="authenticationFailureUrl"><value>/casfailed.jsp</value></property>
		<property name="defaultTargetUrl"><value>/</value></property>
		<property name="filterProcessesUrl"><value>/j_acegi_cas_security_check</value></property>
	</bean>
    
    <bean id="exceptionTranslationFilter" class="org.acegisecurity.ui.ExceptionTranslationFilter">
        <property name="authenticationEntryPoint"><ref local="casProcessingFilterEntryPoint"/></property>
        <property name="accessDeniedHandler">
            <bean class="org.acegisecurity.ui.AccessDeniedHandlerImpl">
                <property name="errorPage" value="/jsps/login/access-denied.jsf"/>
            </bean>
        </property>
    </bean>
    
    <bean id="casProcessingFilterEntryPoint" class="org.acegisecurity.ui.cas.CasProcessingFilterEntryPoint">
        <property name="loginUrl"><value>https://localhost:8443/cas/login</value></property>
        <property name="serviceProperties"><ref bean="serviceProperties"/></property>
    </bean>
    
    <bean id="authenticationManager" class="org.acegisecurity.providers.ProviderManager">
        <property name="providers">
            <list>
                <ref bean="casAuthenticationProvider"/>
                
                <bean class="org.acegisecurity.providers.anonymous.AnonymousAuthenticationProvider">
                    <property name="key" value="changeThis"/>
                </bean>
                <bean class="org.acegisecurity.providers.rememberme.RememberMeAuthenticationProvider">
                    <property name="key" value="changeThis"/>
                </bean>
            </list>
        </property>
    </bean>
    
    <bean id="casAuthenticationProvider" class="org.acegisecurity.providers.cas.CasAuthenticationProvider">
        <property name="casAuthoritiesPopulator"><ref bean="casAuthoritiesPopulator"/></property>
        <property name="casProxyDecider"><ref bean="casProxyDecider"/></property>
        <property name="ticketValidator"><ref bean="casProxyTicketValidator"/></property>
        <property name="statelessTicketCache"><ref bean="statelessTicketCache"/></property>
        <property name="key"><value>my_password_for_this_auth_provider_only</value></property>
    </bean>
    
    <bean id="casProxyTicketValidator" class="org.acegisecurity.providers.cas.ticketvalidator.CasProxyTicketValidator">
        <property name="casValidate"><value>https://localhost:8443/cas/proxyValidate</value></property>
        <!--property name="proxyCallbackUrl"><value>http://localhost:8888/eps//casProxy/receptor</value></property-->
        <property name="serviceProperties"><ref bean="serviceProperties"/></property>
        <property name="trustStore"><value>C:\ProgramFiles\Java\jdk1.5.0_06\jre\lib\security\cacerts</value></property>
    </bean>
    
    <bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
        <property name="configLocation">
            <value>classpath:/ehcache-failsafe.xml</value>
        </property>
    </bean>
    
    <bean id="ticketCacheBackend" class="org.springframework.cache.ehcache.EhCacheFactoryBean">
        <property name="cacheManager">
            <ref local="cacheManager"/>
        </property>
        <property name="cacheName">
            <value>ticketCache</value>
        </property>
    </bean>
    
    <bean id="statelessTicketCache" class="org.acegisecurity.providers.cas.cache.EhCacheBasedTicketCache">
        <property name="cache"><ref local="ticketCacheBackend"/></property>
    </bean>
    
    <bean id="casAuthoritiesPopulator" class="org.acegisecurity.providers.cas.populator.DaoCasAuthoritiesPopulator">
        <!--property name="userDetailsService"><ref bean="inMemoryDaoImpl"/></property-->
        <property name="userDetailsService" ref="userDetailsService"/>
    </bean>
    
    <bean id="inMemoryDaoImpl" class="org.acegisecurity.userdetails.memory.InMemoryDaoImpl">
  		<property name="userMap">
			<value>
                aabdelaziz=PASSWORD_NOT_USED,EPS_SYSTEM_ADMIN
				marissa=PASSWORD_NOT_USED,ROLE_TELLER,ROLE_SUPERVISOR
				dianne=PASSWORD_NOT_USED,ROLE_TELLER
				scott=PASSWORD_NOT_USED,ROLE_TELLER
				peter=PASSWORD_NOT_USED_AND_DISABLED_IGNORED,disabled,ROLE_TELLER
			</value>
		</property>
	</bean>
    
    <bean id="casProxyDecider" class="org.acegisecurity.providers.cas.proxy.RejectProxyTickets"/>
    
    <!-- ===================== HTTP CHANNEL REQUIREMENTS ==================== -->

    <!-- Enabled by default for CAS, as a CAS deployment uses HTTPS -->
    <!--bean id="channelProcessingFilter" class="org.acegisecurity.securechannel.ChannelProcessingFilter">
        <property name="channelDecisionManager"><ref local="channelDecisionManager"/></property>
        <property name="filterInvocationDefinitionSource">
            <value>
                CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
                \A/secure/.*\Z=REQUIRES_SECURE_CHANNEL
                \A/j_acegi_cas_security_check.*\Z=REQUIRES_SECURE_CHANNEL
                \A.*\Z=REQUIRES_INSECURE_CHANNEL
            </value>
        </property>
    </bean>
    
    <bean id="channelDecisionManager" class="org.acegisecurity.securechannel.ChannelDecisionManagerImpl">
        <property name="channelProcessors">
            <list>
               <ref local="secureChannelProcessor"/>
              <ref local="insecureChannelProcessor"/>
            </list>
        </property>
    </bean>
    
    <bean id="secureChannelProcessor" class="org.acegisecurity.securechannel.SecureChannelProcessor"/>
    <bean id="insecureChannelProcessor" class="org.acegisecurity.securechannel.InsecureChannelProcessor"/-->
    <!-- ====================== End of CAS SECURITY CONFIGURATIOS ===================== -->
     
</beans> 

­

­web.xml

Code:
<?xml version = '1.0' encoding = 'windows-1256'?>
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
    <description>Empty web.xml file for Web Application</description>
    <context-param>
        <param-name>javax.faces.CONFIG_FILES</param-name>
        <param-value>/WEB-INF/eps-faces-config.xml</param-value>
    </context-param>
    
    <!-- /WEB-INF/applicationContext.xml         
         -->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:applicationContext.xml,
                     classpath:applicationContext-localDataSource.xml,
                     classpath:applicationContext-acegiSecurity.xml
        </param-value>
    </context-param>
    
    <context-param>
        <param-name>javax.faces.STATE_SAVING_METHOD</param-name>
        <param-value>server</param-value>
        <description>
            State saving method: "client" or "server" (= default)
            See JSF Specification 2.5.2
        </description>
    </context-param>
    
    <context-param>
        <param-name>org.apache.myfaces.ALLOW_JAVASCRIPT</param-name>
        <param-value>true</param-value>
        <description>
            This parameter tells MyFaces if javascript code should be allowed in the
            rendered HTML output.
            If javascript is allowed, command_link anchors will have javascript code
            that submits the corresponding form.
            If javascript is not allowed, the state saving info and nested parameters
            will be added as url parameters.
            Default: "true"
        </description>
    </context-param>
    
    <context-param>
        <param-name>org.apache.myfaces.DETECT_JAVASCRIPT</param-name>
        <param-value>false</param-value>
    </context-param>
    
    <context-param>
        <param-name>org.apache.myfaces.PRETTY_HTML</param-name>
        <param-value>true</param-value>
        <description>
            If true, rendered HTML code will be formatted, so that it is "human readable".
            i.e. additional line separators and whitespace will be written, that do not
            influence the HTML code.
            Default: "true"
        </description>
    </context-param>
    
    <context-param>
        <param-name>org.apache.myfaces.AUTO_SCROLL</param-name>
        <param-value>false</param-value>
        <description>
            If true, a javascript function will be rendered that is able to restore the
            former vertical scroll on every request. Convenient feature if you have pages
            with long lists and you do not want the browser page to always jump to the top
            if you trigger a link or button action that stays on the same page.
            Default: "false"
        </description>
    </context-param>
    
    <filter>
        <filter-name>Acegi Filter Chain Proxy</filter-name>
        <filter-class>org.acegisecurity.util.FilterToBeanProxy</filter-class>
        <init-param>
            <param-name>targetClass</param-name>
            <param-value>org.acegisecurity.util.FilterChainProxy</param-value>
        </init-param>
    </filter>
    
    <filter-mapping>
        <filter-name>Acegi Filter Chain Proxy</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    
    <!-- Faces Servlet -->
    <servlet>
        <servlet-name>Faces Servlet</servlet-name>
        <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
        <load-on-startup> 1 </load-on-startup>
    </servlet>
    <servlet>
        <servlet-name>tiles</servlet-name>
        <servlet-class>org.apache.struts.tiles.TilesServlet</servlet-class>
        <init-param>
            <param-name>definitions-config</param-name>
            <param-value>/WEB-INF/tiles-defs.xml</param-value>
        </init-param>
        <init-param>
            <param-name>definitions-parser-validate</param-name>
            <param-value>true</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>    
    <!-- Faces Servlet Mapping -->
    <servlet-mapping>
        <servlet-name>Faces Servlet</servlet-name>
        <url-pattern>*.jsf</url-pattern>
    </servlet-mapping>
        
    <session-config>
        <session-timeout>35</session-timeout>
    </session-config>
    <mime-mapping>
        <extension>html</extension>
        <mime-type>text/html</mime-type>
    </mime-mapping>
    <mime-mapping>
        <extension>txt</extension>
        <mime-type>text/plain</mime-type>
    </mime-mapping>
    <taglib>
        <taglib-uri>http://java.sun.com/jsf/html</taglib-uri>
        <taglib-location>/WEB-INF/html_basic.tld</taglib-location>
    </taglib>
    <taglib>
        <taglib-uri>http://java.sun.com/jsf/core</taglib-uri>
        <taglib-location>/WEB-INF/jsf_core.tld</taglib-location>
    </taglib>
    <taglib>
        <taglib-uri>http://jakarta.apache.org/struts/tags-tiles</taglib-uri>
        <taglib-location>/WEB-INF/struts-tiles.tld</taglib-location>
    </taglib>
    <taglib>
        <taglib-uri>http://isoftfaces.ae/isoftpicklist</taglib-uri>
        <taglib-location>/WEB-INF/picklist.tld</taglib-location>
    </taglib>
    
    <taglib>
        <taglib-uri>http://isoft.ae/messagecomponent</taglib-uri>
        <taglib-location>/WEB-INF/message.tld</taglib-location>
    </taglib>
    <!-- Start of Extension Filter Part -->
    
    <!-- Extensions Filter -->
    <filter>
        <filter-name>extensionsFilter</filter-name>
        <filter-class>org.apache.myfaces.component.html.util.ExtensionsFilter</filter-class>
        <init-param>
            <param-name>uploadMaxFileSize</param-name>
            <param-value>100m</param-value>
            <description>Set the size limit for uploaded files.
                Format: 10 - 10 bytes
                10k - 10 KB
                10m - 10 MB
                1g - 1 GB
            </description>
        </init-param>
        <init-param>
            <param-name>uploadThresholdSize</param-name>
            <param-value>100k</param-value>
            <description>Set the threshold size - files
                below this limit are stored in memory, files above
                this limit are stored on disk.

                Format: 10 - 10 bytes
                10k - 10 KB
                10m - 10 MB
                1g - 1 GB
            </description>
        </init-param>
    </filter>
    
    <filter-mapping>
        <filter-name>extensionsFilter</filter-name>
        <url-pattern>*.jsf</url-pattern>
    </filter-mapping>
    <filter-mapping>
        <filter-name>extensionsFilter</filter-name>
        <url-pattern>/faces/*</url-pattern>
    </filter-mapping>
    
    <!-- End of Extension Filter Part -->    
    
    <!--  Start Welcome Files -->
    <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>
    <!--  End Welcome Files -->
 
</web-app>

attached contact-cas.war it can use it as sample to test the single sing on CAS. its configured with cas.

also I have attached the web.xml,acegi.xml  files

thats all I hope it helps.


References:

http://forum.springframework.org/archive/index.php/t-12811.html


AttachmentSize
contacts-cas.war2.11 MB
web.xml11.99 KB
cas.war7.85 MB
deployerConfigContext.xml2.72 KB
applicationContext.xml82.8 KB
applicationContext-acegiSecurity.xml10.14 KB

I see the codes here and

I see the codes here and it's complete. I've been looking for them for a while now on the net. - Dennis Wong YOR Health

In a array of colors from

In a array of colors from the http://www.puglias-sporting-goods.com/right.html
archetypal atramentous or white accoutrements to added fashionable dejection and
reds

Powered by Drupal - Design by artinet