Announcement Announcement Module
Collapse
No announcement yet.
spring security 3 and CAS logout Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • spring security 3 and CAS logout

    Hi,

    We have the following problem with spring security not recognizing CAS logouts properly:

    1. User logs in
    2. User logs out
    3. User views anonymous pages ok - application detects they are anonymous
    4. User tries to log in again, instead of a new login page it reuses the expired credentials from step 1.

    We're using Spring Security 3.0.3, CAS server 3.4.3 and CAS client 3.1.12. Here's the relevant configs:

    ROOT security config:

    Code:
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
            xmlns:security="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-3.0.xsd
                http://www.springframework.org/schema/security
                http://www.springframework.org/schema/security/spring-security-3.0.3.xsd">
    
        <security:http entry-point-ref="casProcessingFilterEntryPoint">
    
            <security:intercept-url pattern="/index.jsp" access="ROLE_ANONYMOUS, ROLE_MEMBER" requires-channel="http"/>
            <security:intercept-url pattern="/" access="ROLE_ANONYMOUS, ROLE_MEMBER"  requires-channel="http"/>
    
            <!-- finally a default catch-all. cannot set requires-channel on this because it breaks CAS logout -->
            <security:intercept-url pattern="/**" access="ROLE_MEMBER"/>
    
            <security:anonymous/>
    
            <security:logout invalidate-session="true" logout-url="/logout" logout-success-url="/cas/logout"/>
    
            <security:custom-filter ref="casAuthenticationFilter" after="PRE_AUTH_FILTER"/>
    
            <security:custom-filter ref="casSingleSignOutFilter" after="LOGOUT_FILTER"/>
    
            <security:session-management>
                <security:concurrency-control max-sessions="1" expired-url="/logout"/>
            </security:session-management>
    
        </security:http>
    
        <bean id="serviceProperties" class="org.springframework.security.cas.ServiceProperties">
            <property name="service" value="https://localhost:8443/j_spring_cas_security_check"/>
            <property name="sendRenew" value="false"/>
        </bean>
    
        <security:authentication-manager alias="authenticationManager">
            <security:authentication-provider ref="casAuthenticationProvider"/>
        </security:authentication-manager>
    
        <bean id="casSingleSignOutFilter" class="org.jasig.cas.client.session.SingleSignOutFilter">
        </bean>
    
        <bean id="casAuthenticationFilter" class="org.springframework.security.cas.web.CasAuthenticationFilter">
            <property name="authenticationManager" ref="authenticationManager"/>
            <property name="authenticationFailureHandler">
                <bean class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler">
                    <property name="defaultFailureUrl" value="/casfailed.jsp" />
                </bean>
            </property>
            <property name="authenticationSuccessHandler">
                <bean class="org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler">
                    <property name="defaultTargetUrl" value="/" />
                </bean>
            </property>
        </bean>
    
        <bean id="casProcessingFilterEntryPoint"
            class="org.springframework.security.cas.web.CasAuthenticationEntryPoint">
            <property name="loginUrl" value="https://localhost:8443/cas/login"/>
            <property name="serviceProperties" ref="serviceProperties"/>
        </bean>
    
        <bean id="casAuthenticationProvider" class="org.springframework.security.cas.authentication.CasAuthenticationProvider">
            <property name="userDetailsService" ref="userCredentialsMutatorDao"/>
            <property name="serviceProperties" ref="serviceProperties" />
            <property name="ticketValidator">
                <bean class="org.jasig.cas.client.validation.Cas20ServiceTicketValidator">
                    <constructor-arg index="0" value="https://localhost:8443/cas" />
                    <property name="proxyCallbackUrl" value="https://localhost:8443/secure/receptor" />
                    <property name="proxyGrantingTicketStorage" ref="proxyGrantingTicketStorage" />
                </bean>
            </property>
            <property name="key" value="an_id_for_this_auth_provider_only"/>
        </bean>
    
        <bean id="proxyGrantingTicketStorage" class="org.jasig.cas.client.proxy.ProxyGrantingTicketStorageImpl" />
    
    </beans>
    CAS server security config:

    Code:
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:p="http://www.springframework.org/schema/p"
           xmlns:sec="http://www.springframework.org/schema/security"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
           http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.0.xsd">
    	<description>
    		This is the configuration file for the Spring Security configuration used with the services management tool.  You shouldn't
    		have to modify anything in this file directly.  The configuration options should all be in the cas.properties file.
    	</description>
    
    	<sec:http entry-point-ref="casProcessingFilterEntryPoint" auto-config="true">
    		<sec:intercept-url pattern="/services/loggedout.html" filters="none" /> 
        	<sec:intercept-url pattern="/**" access="${cas.securityContext.serviceProperties.adminRoles}" />
            <sec:logout logout-url="/services/logout.html" logout-success-url="/services/loggedOut.html" />
            <sec:custom-filter ref="casProcessingFilter" after="CAS_FILTER" />
        </sec:http>
    
    	<sec:authentication-manager alias="casAuthenticationManager">
            <sec:authentication-provider ref="casAuthenticationProvider"  />
        </sec:authentication-manager>
    	
    	<bean id="serviceProperties" class="org.springframework.security.cas.ServiceProperties"
    		p:service="${cas.securityContext.serviceProperties.service}"
    		p:sendRenew="false" />
          
    	<bean id="casProcessingFilter" class="org.springframework.security.cas.web.CasAuthenticationFilter"
    		p:authenticationManager-ref="casAuthenticationManager"
    		p:filterProcessesUrl="/services/j_acegi_cas_security_check">
            <property name="authenticationSuccessHandler">
                <bean class="org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler"
                    p:alwaysUseDefaultTargetUrl="true"
                    p:defaultTargetUrl="/services/manage.html" />
            </property>
            <property name="authenticationFailureHandler">
                <bean class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler">
                    <constructor-arg index="0" value="/authorizationFailure.html" />
                </bean>
            </property>
    	</bean>
    
    	<bean id="casProcessingFilterEntryPoint" class="org.springframework.security.cas.web.CasAuthenticationEntryPoint"
    		p:loginUrl="${cas.securityContext.casProcessingFilterEntryPoint.loginUrl}"
    		p:serviceProperties-ref="serviceProperties" />
    
    	<bean id="casAuthenticationProvider" class="org.springframework.security.cas.authentication.CasAuthenticationProvider"
    		p:key="my_password_for_this_auth_provider_only"
    		p:serviceProperties-ref="serviceProperties"
    		p:userDetailsService-ref="userDetailsService">
    	    <property name="ticketValidator">
    	      <bean class="org.jasig.cas.client.validation.Cas20ServiceTicketValidator">
    	        <constructor-arg index="0" value="${cas.securityContext.ticketValidator.casServerUrlPrefix}" />
    	        </bean>
    	    </property>
    	</bean>
    </beans>
    When I click logout (step 2) nothing appears in the console but the correct CAS logout web page is shown.

    However, when I click login (step 4), the correct action is to divert to a members only jsp page, which should trigger a new CAS login screen. Instead it just goes straight to the secured page, renewing the session from the ticket along the way. This appears in the console:

    Code:
    2010-12-17 21:15:40,003 INFO [org.jasig.cas.CentralAuthenticationServiceImpl] - <Granted service ticket [ST-3-SPBYgrAtFrl0KfjFQVBK-cas] for service [https://localhost:8443/j_spring_cas_security_check] for user [raj]>
    2010-12-17 21:15:40,003 INFO [org.jasig.cas.CentralAuthenticationServiceImpl] - <Granted service ticket [ST-3-SPBYgrAtFrl0KfjFQVBK-cas] for service [https://localhost:8443/j_spring_cas_security_check] for user [raj]>
    2010-12-17 21:15:40,035 INFO [org.jasig.cas.authentication.AuthenticationManagerImpl] - <AuthenticationHandler: org.jasig.cas.authentication.handler.support.HttpBasedServiceCredentialsAuthenticationHandler successfully authenticated the user which provided the following credentials: [callbackUrl: https://localhost:8443/secure/receptor]>
    2010-12-17 21:15:40,035 INFO [org.jasig.cas.authentication.AuthenticationManagerImpl] - <AuthenticationHandler: org.jasig.cas.authentication.handler.support.HttpBasedServiceCredentialsAuthenticationHandler successfully authenticated the user which provided the following credentials: [callbackUrl: https://localhost:8443/secure/receptor]>
    163727 [http-8443-1] INFO  org.jasig.cas.client.proxy.ProxyGrantingTicketStorageImpl  - No Proxy Ticket found for [PGTIOU-3-rfqbiZrblbIpqcZi1g0c-cas].
    Any ideas why Spring Security is resurrecting an expired session? Or perhaps why CAS is not invalidating the ticket on logout? I should mention that this behaviour worked fine with Spring Security 2.5 and CAS server 3.3 (I think that was the CAS version).

    Raj.

  • #2
    Are you logging out of CAS rather than just the application? If so, how? If not, then this is normal behaviour.

    Comment


    • #3
      Hi Luke,

      How do you mean? I just have a hyperlink to /logout which isn't a real web page, but redirects to /cas/logout and displays the standard CAS green and white logout page. /cas/logout is just the default logout page on the CAS war deployed in tomcat, it is not part of the ROOT war. I am definitely seeing the CAS green and white logout page, which I would think means I am logging out of CAS too?

      Raj.

      Comment


      • #4
        Ok, so it sounds like you might not be logging out of the application itself?

        Once you have a valid session it won't notice if you log out of CAS separately and you'll still be able to use the application.

        Comment


        • #5
          It sounds like you are looking for single logout. You might have a look at SEC-785 and the CAS Configuring Single Sign Out Documentation.

          Comment


          • #6
            Luke, it appears to be logging out of the application but not CAS. When I hit logout and then go back to the home page the root application thinks I'm an anonymous user again. However when click login the second time around (which is just a members only secured page to trigger the login redirect) instead of calling the login redirect it just hands back the ticket from the previous CAS session.

            This line seems be logging out of the application but not CAS even though the CAS logout page is called?
            Code:
            <security:logout invalidate-session="true" logout-url="/logout" logout-success-url="/cas/logout"/>
            Rwinch, I had all that in my web.xml except for the listener. I added the listener but it didn't make any difference.

            The thing that puzzles me about all this is that CAS single sign on and logout worked fine under Spring 2.5, but when I migrate everything to 3.0 it no longer works.

            Raj.

            Comment


            • #7
              Do you have two different applications or are you referring to the CAS management application? If you are in a different application and you specify /cas/logout it is not the logout url of the cas server because the context root is hit. For example, it might send you to /mywebapp/cas/logout where as you need to go to /cas/logout.

              Try the following flow:

              1) Go to a secured page in your application
              2) Login to CAS
              3) You should see the secured page
              4) Navigate directly to the CAS logout page without using the link (i.e. type https://localhost:9443/cas/logout into the url)
              5) Navigate back to the secured page. Did you get redirected back to CAS for a new ticket? You can test this using at Firefox plugin like tamper data. Did CAS require you to login?

              Comment


              • #8
                Hi Rwinch,

                I finally got it working. First I tried your suggestion and it didn't work correctly, it just did the same thing as before. But then I noticed that the call to /cas/logout was http not SSL. So I changed the path to an absolute path https://localhost:8443/cas/logout and this did the trick.

                Thanks for your help everyone. I find CAS really confusing.

                Comment


                • #10
                  I am having a issue getting case working..

                  Comment

                  Working...
                  X