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?
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 SheepSecurityContextHolder.clearContext()
doesn't clear session data. It removes theThreadLocal
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