Announcement Announcement Module
Collapse
No announcement yet.
Using multiple authentication managers with Spring Security CAS 3.1 Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Using multiple authentication managers with Spring Security CAS 3.1

    New forum member here. My organization has been using Spring Security + CAS for several years and I've been exposed to it off and on over the last two years. I've run into a bit of an issue that I've been banging my head on for the last two days and hope someone can help out.

    The Background
    I have an existing REST(like) application which uses CAS, but have a new requirement to restrict access to functions using different authentication schemes. Basically, the user's id is the same, but for each set of functions (eg /nozzle/** or /claims/**) the query to determine the user's role is different (and the set of roles is different). The approach I am trying to take for this is based off this post http://forum.springsource.org/showth...One-Is-Applied. I'm trying to define two different http elements that will have their own AuthorizationManager/Provider/userDetailsService.

    The Issue
    The main http pattern (/**) seems to work properly, but when I try to go to URLs mapped with the other http pattern (/nozzle/**) URL I get a 403 error. I tried debugging the code and it seems like the provider for /nozzle/** never even gets fired (I only ever see the userDetailsService for the claims side). I suspect I am missing some detail about the way CAS and Spring are working together, anyone have any ideas?

    The Configuration

    Web.xml
    Code:
    		
              <context-param>
    	        <param-name>contextConfigLocation</param-name>
    	        <param-value>
    	        	/WEB-INF/nozzleContext-security.xml,
    	            /WEB-INF/applicationContext-security.xml
    	            
    	        </param-value>
    	    </context-param>
    For /nozzle/**
    Code:
        <sec:http pattern="/nozzle/**" entry-point-ref="casProcessingFilterEntryPoint" authentication-manager-ref="nozzle_authenticationManager">
    		
    		<sec:port-mappings>
    			<sec:port-mapping https="${spring-security.ports.https}" http="${spring-security.ports.http}"/>
    		</sec:port-mappings>
    
    		<sec:intercept-url pattern="/nozzle/**" access="ROLE_X" requires-channel="${spring-security.required.channel}" />
    		<sec:logout logout-success-url="/cas-logout.jsp" />
    		<sec:custom-filter ref="nozzle_casAuthenticationFilter"
    			after="CAS_FILTER" />
    				
    	</sec:http>
    
    	<bean id="nozzle_serviceProperties" class="org.springframework.security.cas.ServiceProperties">
    		<property name="service"
    			value="${cas.service.url}/j_spring_cas_security_check" />
    		<property name="sendRenew" value="false" />
    	</bean>
    	
    	<sec:jdbc-user-service id="nozzle_jdbc-user-service"
    		data-source-ref="datasource"
    		users-by-username-query="anotherQuery" />
    	<sec:debug/>
    
    
    	
    	<bean id="nozzle_authenticationManager" class="org.springframework.security.authentication.ProviderManager">
    		<constructor-arg>
           			<list>
               			<ref bean="nozzle_casAuthenticationProvider"/>
           			</list>
        		</constructor-arg>
    		
    	</bean>
    
    	<bean id="nozzle_casAuthenticationFilter"
    		class="org.springframework.security.cas.web.CasAuthenticationFilter">
    		<property name="authenticationManager" ref="nozzle_authenticationManager" />
    
    		<property name="authenticationFailureHandler">
    			<bean
    				class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler">
    				<property name="defaultFailureUrl" value="/claims/casFailed/" />
    			</bean>
    		</property>
    		<property name="authenticationSuccessHandler">
    			<bean
    				class="{someProprietaryPackage}.security.authentication.DynamizedCookieBasedTargetAuthenticationSuccessHandler">			
    			</bean>
    		</property>
    		<property name="proxyGrantingTicketStorage" ref="proxyGrantingTicketStorage" />
    		<property name="proxyReceptorUrl" value="/secure/receptor" />
    	</bean>
    
    	<bean id="nozzle_casAuthenticationProvider"
    		class="org.springframework.security.cas.authentication.CasAuthenticationProvider">
    		<property name="userDetailsService" ref="nozzle_jdbc-user-service" />
    		<property name="serviceProperties" ref="nozzle_serviceProperties" />
    		<property name="ticketValidator">
    			<bean class="org.jasig.cas.client.validation.Cas20ServiceTicketValidator">
    				<constructor-arg index="0" value="${cas.server.url}" />
    				<property name="proxyGrantingTicketStorage" ref="proxyGrantingTicketStorage" />
    				<property name="proxyCallbackUrl" value="${cas.client.proxyCallbackUrl}" />
    			</bean>
    		</property>
    		<property name="key" value="test" />
    	</bean>
    
    </beans>
    For /**
    Code:
           <bean id="propertyConfigurer"
    		class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
    		<property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE" />
    		<property name="locations">
    			<list>
    				<value>/WEB-INF/application-${env}.properties
    				</value>
    			</list>
    		</property>
    	</bean>
    
    	 <sec:http pattern="/**" use-expressions="true" entry-point-ref="casProcessingFilterEntryPoint" authentication-manager-ref="mainAuthenticationManager">
    		
    		<sec:port-mappings>
    			<sec:port-mapping https="${spring-security.ports.https}" http="${spring-security.ports.http}"/>
    		</sec:port-mappings>
    		<sec:request-cache ref="casRequestCache"/>
    		<sec:intercept-url pattern="/claims/**"
    			access="hasAnyRole('ROLE_A')"
    			requires-channel="${spring-security.required.channel}" />
    		<sec:logout logout-success-url="/cas-logout.jsp" />
    		<sec:custom-filter ref="casAuthenticationFilter"
    			after="CAS_FILTER" />
    	</sec:http>
    	
    	<bean id="casRequestCache" class="{someProprietaryPackage}.security.authentication.CookieFallbackHttpSessionRequestCache">
    		<property name="requireHttps">
    			<value type="java.lang.Boolean">${cas.server.successHandler.requireHttps}</value>	
    		</property>	
    		<property name="portResolver" ref="portResolver"/>	
    	</bean>
    	
    	<bean id="portResolver" class="org.springframework.security.web.PortResolverImpl">
    		<property name="portMapper" ref="portMapper"/>
    	</bean>
    	
    	<bean id="portMapper" class="org.springframework.security.web.PortMapperImpl">
    		<property name="portMappings">
    			<map>
    				<entry key="${spring-security.ports.http}" value="${spring-security.ports.https}"/>
    			</map>
    		</property>
    	</bean>
    	
    	<bean id="datasource" class="org.springframework.jndi.JndiObjectFactoryBean">
    		<property name="jndiName" value="${spring-security.db.jndi.name}" />
    		<property name="lookupOnStartup" value="false" />
    		<property name="cache" value="true" />
    		<property name="proxyInterface" value="javax.sql.DataSource" />
    	</bean>
    
    	<sec:jdbc-user-service id="jdbc-user-service"
    		data-source-ref="datasource"
    		users-by-username-query="someQuery" />
    
    
    	<bean id="mainAuthenticationManager" class="org.springframework.security.authentication.ProviderManager">
    		<constructor-arg>
           		<list>
               		<ref bean="casAuthenticationProvider"/>
           		</list>
        	</constructor-arg>
    	</bean>
    
    	<bean id="casAuthenticationFilter"
    		class="org.springframework.security.cas.web.CasAuthenticationFilter">
    		<property name="authenticationManager" ref="mainAuthenticationManager" />
    
    		<property name="authenticationFailureHandler">
    		
    			<bean
    				class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler">
    				<property name="defaultFailureUrl" value="/claims/casFailed/" />
    			</bean>
    		</property>
    		<property name="authenticationSuccessHandler">
    			<bean
    				class="{someProprietaryPackage}.security.authentication.DynamizedCookieBasedTargetAuthenticationSuccessHandler">			
    			</bean>
    		</property>
    		<property name="proxyGrantingTicketStorage" ref="proxyGrantingTicketStorage" />
    		<property name="proxyReceptorUrl" value="/secure/receptor" />
    	</bean>
    
    	<bean id="casProcessingFilterEntryPoint"
    		class="org.springframework.security.cas.web.CasAuthenticationEntryPoint">
    		<property name="loginUrl" value="${cas.server.url}/login" />
    		<property name="serviceProperties" ref="serviceProperties" />
    	</bean>
     
    	<bean id="casAuthenticationProvider"
    		class="org.springframework.security.cas.authentication.CasAuthenticationProvider">
    		<property name="userDetailsService" ref="jdbc-user-service" />
    		<property name="serviceProperties" ref="serviceProperties" />
    		<property name="ticketValidator">
    			<bean class="org.jasig.cas.client.validation.Cas20ServiceTicketValidator">
    				<constructor-arg index="0" value="${cas.server.url}" />
    				<property name="proxyGrantingTicketStorage" ref="proxyGrantingTicketStorage" />
    				<property name="proxyCallbackUrl" value="${cas.client.proxyCallbackUrl}" />
    			</bean>
    		</property>
    		<property name="key" value="test2" />
    	</bean>
    
    	<bean id="proxyGrantingTicketStorage"
    		class="org.jasig.cas.client.proxy.ProxyGrantingTicketStorageImpl" />
    
    	<bean id="serviceProperties" class="org.springframework.security.cas.ServiceProperties">
    		<property name="service"
    			value="${cas.service.url}/j_spring_cas_security_check" />
    		<property name="sendRenew" value="false" />
    	</bean>
    </beans>
    Last edited by Talmage; Jun 20th, 2013, 05:54 PM. Reason: trying to clean up formatting/clarifications

  • #2
    you can implement
    Code:
    public class AuthenticationDetailsSourceImpl implements AuthenticationDetailsSource<HttpServletRequest,WebAuthenticationDetailsExt> {
    
    	public WebAuthenticationDetailsExt buildDetails(HttpServletRequest context) {
    		return new WebAuthenticationDetailsExt(context);
    	}
    
    }
    with
    Code:
    public class WebAuthenticationDetailsExt extends WebAuthenticationDetails {
    
    	private HttpServletRequest request;
    
    	public WebAuthenticationDetailsExt(HttpServletRequest request) {
    		super(request);
    		this.request = request;
    	}
    	
    	public HttpServletRequest getRequest() {
    		return request;
    	}
    
    }
    and configuration :
    Code:
    <bean id="digest-filter"
    		class="org.springframework.security.web.authentication.www.DigestAuthenticationFilter"
    		p:userDetailsService-ref="user-service"
    		p:authenticationEntryPoint-ref="digest-entry-point" 
    		p:userCache-ref="user-cache"
    		p:authenticationDetailsSource-ref="authentication-details-source"
    		/>
    now you can call
    Code:
    WebAuthenticationDetailsExt details = (WebAuthenticationDetailsExt) authentication.getDetails();
    and verify url

    Comment


    • #3
      Hey, thanks for the reply. I'm not really sure I follow your suggestions though. Are you suggesting I can't do this in the configuration using multiple http namespace(aka FilterChainProxy) items?

      Comment

      Working...
      X