197
votes

I'm trying to integrate Spring Security SAML Extension with Spring Boot.

About the matter, I did develop a complete sample application. Its source code is available on GitHub:

By running it as Spring Boot application (running against the SDK built-in Application Server), the WebApp works fine.

Unfortunately, the same AuthN process doesn't work at all on Undertow/WildFly.

According to the logs, the IdP actually performs the AuthN process: the instructions of my custom UserDetails implementation are correctly executed. Despite the execution flow, Spring doesn't set up and persist the privileges for the current user.

@Component
public class SAMLUserDetailsServiceImpl implements SAMLUserDetailsService {

    // Logger
    private static final Logger LOG = LoggerFactory.getLogger(SAMLUserDetailsServiceImpl.class);

    @Override
    public Object loadUserBySAML(SAMLCredential credential)
            throws UsernameNotFoundException, SSOUserAccountNotExistsException {
        String userID = credential.getNameID().getValue();
        if (userID.compareTo("jdoe@samplemail.com") != 0) {     // We're simulating the data access.
            LOG.warn("SSO User Account not found into the system");
            throw new SSOUserAccountNotExistsException("SSO User Account not found into the system", userID);
        }
        LOG.info(userID + " is logged in");
        List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
        GrantedAuthority authority = new SimpleGrantedAuthority("ROLE_USER");
        authorities.add(authority);
        ExtUser userDetails = new ExtUser(userID, "password", true, true, true,
                true, authorities, "John", "Doe");
        return userDetails;
    }
}

While debugging, I found out the problem relies on the FilterChainProxy class. At runtime, the attribute FILTER_APPLIED of ServletRequest has a null value, thus Spring clears the SecurityContextHolder.

private final static String FILTER_APPLIED = FilterChainProxy.class.getName().concat(".APPLIED");

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
        throws IOException, ServletException {
    boolean clearContext = request.getAttribute(FILTER_APPLIED) == null;
    if (clearContext) {
        try {
            request.setAttribute(FILTER_APPLIED, Boolean.TRUE);
            doFilterInternal(request, response, chain);
        } finally {
            SecurityContextHolder.clearContext();
            request.removeAttribute(FILTER_APPLIED);
        }
    } else {
        doFilterInternal(request, response, chain);
    }
}

On VMware vFabric tc Sever and Tomcat, everything works totally fine. Do you have any idea about solving this issue?

1
In most situations, the SecurityContextHolder should be cleared after a request. The only purpose of that code is in case the filter chain is applied more than once during the same request (in which case, only the original chain should clear the context). So I don't think that's an issue.Shaun the Sheep
BTW, this behaviour invalids the login process every time. Is there a way to fix it, for instance by properly configuring my software of the AS?vdenotaris
Not sure what you mean by this. What behaviour, and how does it invalidate the login? Clearing the context when a thread finishes handling a request is normal behaviour - it's essential to prevent leaking thread-local data back to a thread pool. At that point the context should usually be cached in the user's session. So it shouldn't invalidate a login.Shaun the Sheep
As described above, after the SSO, the Application Server clears session data and auth data. This occurs only with Wildfly: the same code works fine with Tomcat.vdenotaris
SecurityContextHolder.clearContext() doesn't clear session data. It removes the ThreadLocal storage of the context prior to releasing a thread back to the thread pool. My point is that this should always happen at the end of a request, so what you are seeing is normal and not likely to be the cause of your problem.Shaun the Sheep

1 Answers

7
votes

Investigating the problem I have noticed that there is some mess with cookies and referers in the auth request.

Currently wildfly authentication will work if you change webapplication context to the Root Context:

 <server name="default-server" default-host="webapp">
     <http-listener name="default" socket-binding="http"/>
     <host name="default-host" alias="localhost" default-web-module="sso.war"/>
 </server>

After restarting wildfly and clearing cookies all should work as expected