How to conditionally skip the SecurityContextPersistenceFilter filter in Grails Spring Security plugin filter chain
Asked Answered
C

2

6

I have a unique scenario I'm trying to resolve under the constraints of the Spring Security plugin (version 1.2.7.3 if currious). I have created a custom SSO plugin that allows login with a signed URL. The custom plugin works great, and I have added according to the documentation by creating the beans in resources.groovy and adding into the filter chain within BootStrap.groovy.

SpringSecurityUtils.clientRegisterFilter('ssoFilter', SecurityFilterPosition.SECURITY_CONTEXT_FILTER.order + 10)

Once a user is signed in everything works great and the existing active session that was added to the security context authenticates the user.

I have a use case where it is possible that a user who is already authenticated may come back on the same browser (i.e. same session cookie) with a different user on an SSO request. I'd like to have the filter chain notice the 'sso=true' in the query string of the URL.

The behavior I'm seeing now is that the SSO is never reached because the original user is already authenticated by the security context. I can't add the SSO filter before the SecurityContextPersistenceFilter as that causes issues where the SSO filter is constantly hit and nothing actually gets rendered. This follows docs where I've seen it saying that you shouldn't put any filters ahead of the security context filter.

I had looked into creating a special filter chain specifically for URLs with 'sso=true' (something I am doing during the unauthenticated flow by adding a custom RequestMatcher and AuthenticationEntryPoint implementation to the DelegatingAuthenticationEntryPoint) by using the springsecurity.filterChain.chainMap config saying. However, it appears from docs and experiments that only the path is filtered.

Is there a way to ensure that whenever 'sso=true' is seen on the URL, that the SSO filter is hit while still having availability to the security context or that the SecurityContextPersistenceFilter can pass through the request to the SSO filter?

Commuter answered 10/5, 2015 at 0:50 Comment(0)
B
5

It seems to me that you could use a custom SecurityContextRepository.

Version 1.2.7.3 of the Spring Security Grails plugin appears to use Spring Security 3.0.7. As mentioned in Section 8.3.1 of the Spring Security reference, from Spring Security 3.0 onward, the SecurityContextPersistenceFilter is configured with a SecurityContextRepository bean, which is responsible for loading and saving the SecurityContext. By default, this is an instance of HttpSessionSecurityContextRepository.

You could create a custom class that extends HttpSessionSecurityContextRepository. The custom subclass could override the loadContext(HttpRequestResponseHolder) method to delete the "SPRING_SECURITY_CONTEXT" session attribute if the request contains the sso=true query parameter.

You can view the implementation of HttpSessionSecurityContextRepository in Spring Security 3.0.7 on GitHub:
https://github.com/spring-projects/spring-security/blob/3.0.7.RELEASE/web/src/main/java/org/springframework/security/web/context/HttpSessionSecurityContextRepository.java

Related: How can I use Spring Security without sessions?

Bashemath answered 4/6, 2015 at 23:18 Comment(0)
R
1

Daniel, Your solution worked. Here's my snippet

@Override
public SecurityContext loadContext(HttpRequestResponseHolder requestResponseHolder) {
    logger.debug("loadContext entry");
    String ssoParameter = requestResponseHolder.getRequest().getParameter("sso");

    if (ssoParameter != null && ssoParameter.equalsIgnoreCase("true")) {
        HttpSession session = requestResponseHolder.getRequest().getSession(false);
        if (session != null) session.invalidate();
    }
    return super.loadContext(requestResponseHolder);
}
Romantic answered 30/7, 2015 at 17:58 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.