I need to use a legacy UserDetailsService
with Spring Security SAML2, so I'm following these instructions from Spring. However, I get an error when I just try to replace the AuthenticationProvider
with the supposedly "default" one according to that documentation:
public class WigWebSecurityConfiguration extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
OpenSaml4AuthenticationProvider authenticationProvider = new OpenSaml4AuthenticationProvider();
// I've tried removing these 2 lines and I get the same error
authenticationProvider.setAssertionValidator(OpenSaml4AuthenticationProvider.createDefaultAssertionValidator());
authenticationProvider.setResponseAuthenticationConverter(OpenSaml4AuthenticationProvider.createDefaultResponseAuthenticationConverter());
httpSecurity.authorizeRequests(authz -> authz.anyRequest().authenticated())
.saml2Login(saml2 -> saml2.authenticationManager(new ProviderManager(authenticationProvider)));
}
}
When I do this, I get the following error when I try to authenticate:
java.lang.NoSuchMethodError: org.opensaml.saml.saml2.assertion.SAML20AssertionValidator.<init>(Ljava/util/Collection;Ljava/util/Collection;Ljava/util/Collection;Lorg/opensaml/saml/saml2/assertion/AssertionValidator;Lorg/opensaml/xmlsec/signature/support/SignatureTrustEngine;Lorg/opensaml/xmlsec/signature/support/SignaturePrevalidator;)V
at org.springframework.security.saml2.provider.service.authentication.OpenSaml4AuthenticationProvider$SAML20AssertionValidators$3.<init>(OpenSaml4AuthenticationProvider.java:732)
at org.springframework.security.saml2.provider.service.authentication.OpenSaml4AuthenticationProvider$SAML20AssertionValidators.<clinit>(OpenSaml4AuthenticationProvider.java:731)
at org.springframework.security.saml2.provider.service.authentication.OpenSaml4AuthenticationProvider.lambda$createDefaultAssertionSignatureValidator$8(OpenSaml4AuthenticationProvider.java:572)
at org.springframework.security.saml2.provider.service.authentication.OpenSaml4AuthenticationProvider.lambda$createAssertionValidator$11(OpenSaml4AuthenticationProvider.java:654)
at org.springframework.security.saml2.provider.service.authentication.OpenSaml4AuthenticationProvider.process(OpenSaml4AuthenticationProvider.java:495)
at org.springframework.security.saml2.provider.service.authentication.OpenSaml4AuthenticationProvider.authenticate(OpenSaml4AuthenticationProvider.java:448)
at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:182)
at org.springframework.security.saml2.provider.service.servlet.filter.Saml2WebSsoAuthenticationFilter.attemptAuthentication(Saml2WebSsoAuthenticationFilter.java:113)
at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:222)
at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:212)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
But when I use the same code without setting the authenticationManager
, then the SAML authentication works fine. (Any page that wants to use my custom UserDetails
fails of course, because it's not being populated, but all the SAML authentication steps are working fine.):
public class WigWebSecurityConfiguration extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity.authorizeRequests(authz -> authz.anyRequest().authenticated())
.saml2Login();
}
}
It turns out that I was using org.opensaml:opensaml-api 3.4.6, and you need to be using 4.x to use the class OpenSaml4AuthenticationProvider
. If you're using 3.x you need to use the deprecated class OpenSamlAuthenticationProvider
. I wasn't able to upgrade the opensaml dependency because I'm using Java 8, so this is the code that works for me:
public class WigWebSecurityConfiguration extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
// This class is deprecated, but you have to use it if you're using OpenSAML < 4.0
OpenSamlAuthenticationProvider authenticationProvider = new OpenSamlAuthenticationProvider();
authenticationProvider.setAssertionValidator(OpenSamlAuthenticationProvider.createDefaultAssertionValidator());
authenticationProvider.setResponseAuthenticationConverter(OpenSamlAuthenticationProvider.createDefaultResponseAuthenticationConverter());
httpSecurity.authorizeRequests(authz -> authz.anyRequest().authenticated())
.saml2Login(saml2 -> saml2.authenticationManager(new ProviderManager(authenticationProvider)));
}
}
I finally found the answer when I discovered that that is what Saml2LoginConfigurer does internally.