Announcement Announcement Module
Collapse
No announcement yet.
cas, spring security, proxy authentication Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • cas, spring security, proxy authentication

    Hello,

    I am trying to set up a CAS client with spring security.

    I can get the secured resource after login on cas, but I can't get a PT using the code below.

    Code:
    ((CasAuthenticationToken) SecurityContextHolder.getContext().getAuthentication())
        .getAssertion().getPrincipal().getProxyTicketFor(targetService);
    the return value is always null.

    I use "http://localhost:8080/anotherTest/j_spring_cas_security_check" as the targetService, am I wrong?

    or something else I missed in my config, any help will be appreciated.

    Here are my config files:

    web.xml:

    Code:
    <?xml version="1.0" encoding="UTF-8"?> 
    <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
            xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" 
            xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" 
            id="WebApp_ID" version="2.5"> 
            <display-name>test</display-name> 
    
            <context-param> 
                    <param-name>contextConfigLocation</param-name> 
                    <param-value> 
                            /WEB-INF/securityContext.xml 
                    </param-value> 
            </context-param> 
    
             <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> 
    
            <listener> 
                    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> 
            </listener> 
    
            <servlet> 
                    <servlet-name>test</servlet-name> 
                    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> 
                    <load-on-startup>2</load-on-startup> 
            </servlet> 
    
            <servlet-mapping> 
                    <servlet-name>test</servlet-name> 
                    <url-pattern>/*</url-pattern> 
            </servlet-mapping> 
    </web-app>
    securityContext.xml:

    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/security http://www.springframework.org/schema/security/spring-security-3.0.xsd
                    http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> 
    
            <sec:http entry-point-ref="casProcessingFilterEntryPoint"> 
        <sec:intercept-url pattern="/**" access="ROLE_USER" /> 
            <sec:custom-filter ref="casProcessingFilter" after="CAS_FILTER" /> 
        </sec:http> 
            
            <bean id="serviceProperties" class="org.springframework.security.cas.ServiceProperties" 
                    p:service="http://localhost:8080/test/j_spring_cas_security_check" 
                    p:sendRenew="false" /> 
                    
            <bean id="casProcessingFilterEntryPoint" class="org.springframework.security.cas.web.CasAuthenticationEntryPoint" 
                    p:loginUrl="http://localhost:8080/cas/login" 
                    p:serviceProperties-ref="serviceProperties" /> 
          
            <bean id="casProcessingFilter" class="org.springframework.security.cas.web.CasAuthenticationFilter" 
                    p:authenticationManager-ref="casAuthenticationManager" 
                    p:filterProcessesUrl="/j_spring_cas_security_check"> 
                    <property name="proxyGrantingTicketStorage" ref="proxyGrantingTicketStorage" /> 
                    <property name="proxyReceptorUrl" value="/secure/receptor" /> 
            </bean> 
                    
            <sec:authentication-manager alias="casAuthenticationManager"> 
            <sec:authentication-provider ref="casAuthenticationProvider"  /> 
        </sec:authentication-manager> 
    
            <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.Cas20ProxyTicketValidator"> 
                                    <constructor-arg index="0" value="http://localhost:8080/cas" /> 
                                    <property name="proxyGrantingTicketStorage" ref="proxyGrantingTicketStorage" /> 
                                    <property name="proxyCallbackUrl" 
                                            value="http://localhost:8080/test/secure/receptor" /> 
                                    <property name="proxyRetriever"> 
                                            <bean class="org.jasig.cas.client.proxy.Cas20ProxyRetriever"> 
                                                    <constructor-arg index="0" value="http://localhost:8080/cas"></constructor-arg> 
                                            </bean> 
                                    </property> 
                                    <property name="acceptAnyProxy" value="true"></property> 
                            </bean> 
                    </property> 
            </bean> 
            
            <bean id="proxyGrantingTicketStorage" class="org.jasig.cas.client.proxy.ProxyGrantingTicketStorageImpl" /> 
            
            <bean id="userDetailsService" 
                    class="org.springframework.security.core.userdetails.memory.InMemoryDaoImpl"> 
                    <property name="userProperties"> 
                            <props> 
                                    <prop key="test">test, ROLE_USER, enabled</prop> 
                            </props> 
                    </property> 
            </bean> 
    </beans>

  • #2
    It is hard to say, but I would take a look at the logs on the CAS Server / Spring Security side (you may need to enable them). I'm guessing this is due to the fact that CAS ensures that you have a valid SSL connection before sending the proxy ticket and that SSL connection is failing (looks like you have http endpoints configured). Of course CAS can be customized to ignore the SSL handshakes, but I cannot be certain you have that setup correctly. In short, I would look at the logs and if that doesn't help post them and perhaps I or someone else will be able to help.

    Cheers,

    Comment


    • #3
      Thank you, Rob. Yesterday is Chinese New Year, so happy new year

      You are right ,the proxy callback needs HTTPS.

      Here's a snippet in the CAS Protocol(www.jasig.org/cas/protocol).

      The proxy callback mechanism works as follows:

      The service that is requesting a proxy-granting ticket specifies upon initial service ticket or proxy ticket validation the HTTP request parameter "pgtUrl" to /serviceValidate (or /proxyValidate). This is a callback URL of the service to which CAS will connect to verify the service's identity. This URL MUST be HTTPS, and CAS MUST verify both that the SSL certificate is valid and that its name matches that of the service. If the certificate fails validation, no proxy-granting ticket will be issued, and the CAS service response as described in Section 2.5.2 MUST NOT contain a <proxyGrantingTicket> block. At this point, the issuance of a proxy-granting ticket is halted, but service ticket validation will continue, returning success or failure as appropriate. If certificate validation is successful, issuance of a proxy-granting ticket proceeds as in step 2.
      I think it is so tricky that the issuance of a proxy-granting ticket is halted without any hint, and the service ticket validation will continue. Any warn or info will save much time to figure this out.

      Now I encounter another problem, "Could not access HTTP invoker remote service". It can be accessed with BASIC_AUTH_FILTER, but not with CAS_FILTER.

      Must I use the BASIC_AUTH_FILTER ? or my idea is to simple with the CAS_FILTER ?

      I export a remote service via HttpInvokerServiceExporter, and secure it with CasAuthenticationFilter. On the HttpInvoker client side I invoke it with a PT added to the request by implementing a subclass of CommonsHttpInvokerRequestExecutor.(refer to Spring Remoting with Security and SSL by Mattias Hellborg Arthursson)

      Code:
      public class CasAuthenticationCommonsHttpInvokerRequestExecutor extends
      		CommonsHttpInvokerRequestExecutor {
      	
      	@Override
      	protected PostMethod createPostMethod(HttpInvokerClientConfiguration config) throws IOException {
      		PostMethod postMethod = super.createPostMethod(config);
      		String ticket = ((CasAuthenticationToken)SecurityContextHolder.getContext().getAuthentication()).getAssertion().getPrincipal().getProxyTicketFor("https://localhost:8443/anotherTest/j_spring_cas_security_check");
      		postMethod.addRequestHeader("ticket", new String(Base64.encode(ticket.getBytes())));
      //		postMethod.addParameter("ticket", new String(Base64.encode(ticket.getBytes())));
      //		postMethod.setRequestHeader("ticket", new String(Base64.encode(ticket.getBytes())));
      		return postMethod;
      	}
      }
      remoting.xml:
      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"
      	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
      
      	<bean name="/test" class="test.TestController"
      		autowire="byName" />
      
      	<bean id="testService"
      		class="org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean">
      		<property name="serviceUrl"
      			value="https://localhost:8443/anotherTest/testService" />
      		<property name="serviceInterface"
      			value="test.InterfaceTestService" />
      		<property name="httpInvokerRequestExecutor" ref="httpInvokerRequestExecutor" />
      	</bean>
      
      	<bean id="httpInvokerRequestExecutor"
      		class="test.CasAuthenticationCommonsHttpInvokerRequestExecutor" />
      </beans>

      Comment


      • #4
        In order for proxy authentication to work with Spring Security you currently need to post to a specific URL (it does not support every URL) with the appropriate parameter in the request. See https://jira.springsource.org/browse/SEC-965 for details

        Comment


        • #5
          Thanks Rob, your replies help a lot.

          Comment


          • #6
            Hello all,

            I'm new to spring security and CAS.
            I'm facing against similar problem and looking for help.

            On server SrvA I have CAS, on SrvB I have client, on SrvC I have remote services which I have to secure with CAS.

            Everything is all right between SrvA and SrvB, but when I invoke remote service via custom HttpInvokerServiceExporter (extends CommonsHttpInvokerRequestExecutor and adds ProxyTicket) all I get is following exception:

            Code:
            2011-02-25 07:13:44 org.apache.catalina.core.StandardWrapperValve invoke
            SEVERE: Servlet.service() for servlet appServlet threw exception
            org.apache.commons.httpclient.HttpException: Did not receive successful HTTP response: status code = 302, status message = [Moved Temporarily]
            	at org.springframework.remoting.httpinvoker.CommonsHttpInvokerRequestExecutor.validateResponse(CommonsHttpInvokerRequestExecutor.java:214)
            	at org.springframework.remoting.httpinvoker.CommonsHttpInvokerRequestExecutor.doExecuteRequest(CommonsHttpInvokerRequestExecutor.java:131)
            	at org.springframework.remoting.httpinvoker.AbstractHttpInvokerRequestExecutor.executeRequest(AbstractHttpInvokerRequestExecutor.java:136)
            	at org.springframework.remoting.httpinvoker.HttpInvokerClientInterceptor.executeRequest(HttpInvokerClientInterceptor.java:192)
            	at org.springframework.remoting.httpinvoker.HttpInvokerClientInterceptor.executeRequest(HttpInvokerClientInterceptor.java:174)
            	at org.springframework.remoting.httpinvoker.HttpInvokerClientInterceptor.invoke(HttpInvokerClientInterceptor.java:142)
            	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
            	at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
            	at $Proxy17.sayHello(Unknown Source)
            	at security.test.HomeController.home(HomeController.java:43)
            	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
            	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
            	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
            	at java.lang.reflect.Method.invoke(Method.java:597)
            	at org.springframework.web.bind.annotation.support.HandlerMethodInvoker.invokeHandlerMethod(HandlerMethodInvoker.java:176)
            	at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.invokeHandlerMethod(AnnotationMethodHandlerAdapter.java:426)
            	at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.handle(AnnotationMethodHandlerAdapter.java:414)
            	at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:790)
            	at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:719)
            	at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:644)
            	at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:549)
            	at javax.servlet.http.HttpServlet.service(HttpServlet.java:617)
            	at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
            	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
            	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
            	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:312)
            	at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:116)
            	at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:83)
            	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:324)
            	at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:95)
            	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:324)
            	at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:100)
            	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:324)
            	at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:79)
            	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:324)
            	at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:54)
            	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:324)
            	at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:35)
            	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:324)
            	at org.springframework.security.web.authentication.www.BasicAuthenticationFilter.doFilter(BasicAuthenticationFilter.java:119)
            	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:324)
            	at org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter.doFilter(DefaultLoginPageGeneratingFilter.java:91)
            	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:324)
            	at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:187)
            	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:324)
            	at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:187)
            	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:324)
            	at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:105)
            	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:324)
            	at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:80)
            	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:324)
            	at org.springframework.security.web.session.ConcurrentSessionFilter.doFilter(ConcurrentSessionFilter.java:109)
            	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:324)
            	at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:165)
            	at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:237)
            	at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:167)
            	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
            	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
            	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
            	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
            	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
            	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
            	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
            	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:298)
            	at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:852)
            	at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:588)
            	at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
            	at java.lang.Thread.run(Thread.java:619)
            Can You help me?
            My configuration is similar to bolin's.
            Last edited by piotrj; Feb 25th, 2011, 04:18 AM.

            Comment


            • #7
              First please start a new thread (post a link from here to that new thread) for new discussions. This helps to ensure others can find answers easier. On that thread please be sure to include your configuration, what you are doing, what is happening, and what you want to happen.

              Cheers,

              Comment

              Working...
              X