spring-securitycasjasigspring-security-cas

Setting up Pre auth filter for CasAuthenticationFilter


I've a Spring Jasig CAS SSO set up for a couple of applications. This uses CasAuthenticationFilter. So I've webapps set up like these -

Cas Server (Cas 3.5.2) - Cas.war, App1 - App1.war and App2 - App2.war. Applications use Spring 3.2.3 and Spring Security 3.1.4.RELEASE.

Spring Security Config: http://pastie.org/private/qxcx1h8i9ys0w3lmwegiw

Things seem to work normally with this setup. Now, when I enable OAuth at the Cas Server (not through Spring Cas), I'm unable to integrate that authentication with the usual form-based authentication that I've set up. Facebook OAuth integration seems to work fine as I can see facebook profile attributes successfully retrieved in the logs. The problem is that post facebook login, CasAuthenticationFilter tries to authenticate the user "FacebookProfile#XYZXYZ" with a similar mechanism for form-based login and obviously it doesn't find that user in the database table for users. My guess is that I need to write a custom filter that extends AbstractPreAuthenticatedProcessingFilter and with position before PRE_AUTH_FILTER (check the pastie configuration above) and that should somehow set the Authentication right, so CasAuthenticationFilter should know that the user is already logged in.

This is the URL being authenticated by CasAuthenticationFilter as per the logs - /j_spring_cas_security_proxyreceptor?pgtIou=PGTIOU-1-pR9r9LVJvB5EkezbMJHN-talenteye.in&pgtId=TGT-2-QXvAHIRciBNR9HU5FOvpOaHcJaBj5OJTUPPz5ZwA7yK1xH54iL-myorg.in

The implementation requiresAuthentication of CasAuthenticationFilter looks like this:

protected boolean requiresAuthentication(final HttpServletRequest request, final HttpServletResponse response) {
    final boolean serviceTicketRequest = serviceTicketRequest(request, response);
    final boolean result = serviceTicketRequest || proxyReceptorRequest(request) || (proxyTicketRequest(serviceTicketRequest, request));
    if(logger.isDebugEnabled()) {
        logger.debug("requiresAuthentication = "+result);
    }
    return result;
}

And the logs say -

19:23:42.835 [http-bio-8080-exec-8] DEBUG o.s.s.c.web.CasAuthenticationFilter -     serviceTicketRequest = false
19:23:42.835 [http-bio-8080-exec-8] DEBUG o.s.s.c.web.CasAuthenticationFilter - proxyReceptorConfigured = true
19:23:42.835 [http-bio-8080-exec-8] DEBUG o.s.s.c.web.CasAuthenticationFilter - proxyReceptorRequest = true
19:23:42.835 [http-bio-8080-exec-8] DEBUG o.s.s.c.web.CasAuthenticationFilter - requiresAuthentication = true
19:23:42.835 [http-bio-8080-exec-8] DEBUG o.s.s.c.web.CasAuthenticationFilter - Request is to process authentication
19:23:42.835 [http-bio-8080-exec-8] DEBUG o.s.s.c.web.CasAuthenticationFilter - proxyReceptorConfigured = true
19:23:42.835 [http-bio-8080-exec-8] DEBUG o.s.s.c.web.CasAuthenticationFilter - proxyReceptorRequest = true
19:23:42.835 [http-bio-8080-exec-8] DEBUG o.s.s.c.web.CasAuthenticationFilter - Responding to proxy receptor request

I'm confused as to how to make this work together. I wonder if I'm complicating things a bit too much. Any pointers will be really helpful as I've already wasted a couple of days on this.


Solution

  • I resolved this myself and hence posting here for others who face similar issues.

    The whole point of using CAS is to centralize the authentication. I wrote a custom class that extends AbstractCasAssertionUserDetailsService. This doesn't do the authentication. It has to be done on the CAS server. This just prepares a UserDetails object which is used by the CAS client web applications. So, PRE-AUTH was not needed in my case. Also, I got rid of unneeded proxy receptor configuration. It works well now.