I'm using spring-security-saml2-service-provider
for authentication in one of my spring boot applications and I'm using a custom JwtAuthorizationFilter
(via a http Authentication header) in a different spring boot application.
They both work perfectly on their own.
Now I need to write a spring boot application that uses both of them. If the JWT token is available (Authentication header), then use the JwtAuthorizationFilter
, otherwise use saml2Login
.
The SAML2 configuration looks like this: (There is no filter, just the saml2Login
)
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf()
.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()).and()
.antMatcher("/**").authorizeRequests()
.antMatchers("/saml2/service-provider-metadata/**").permitAll()
.antMatchers("/**").authenticated().and()
// use SAML2
.saml2Login()
.addObjectPostProcessor(new ObjectPostProcessor<OpenSamlAuthenticationProvider>() {
public <O extends OpenSamlAuthenticationProvider> O postProcess(O samlAuthProvider) {
samlAuthProvider.setAuthoritiesExtractor(authoritiesExtractor());
samlAuthProvider.setAuthoritiesMapper(authoritiesMapper());
return samlAuthProvider;
}
})
;
}
The JWT configuration looks like this:
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf()
.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()).and()
.antMatcher("/**").authorizeRequests()
.antMatchers("/**").authenticated().and()
// use JWT
.addFilter(new JwtAuthorizationFilter(authenticationManager(), jwtUtil))
;
}
I think I need something like a JwtOrSaml2AuthenticationFilter
but don't know how to do that.
The solution is to
Set a header based requestMatcher before the addFilter
@EnableWebSecurity
public class SecurityConfiguration {
@Order(100) // lower number = higher priority
@Configuration
@RequiredArgsConstructor
public static class AppSecurityJWT extends WebSecurityConfigurerAdapter {
final JWTUtil jwtUtil;
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()).and()
.antMatcher("/**").authorizeRequests()
.antMatchers("/saml2/service-provider-metadata/**", "/idm-app/**").permitAll()
.antMatchers("/**").authenticated().and()
// This configuration will only be active if the Authorization header is present in the request
.requestMatcher(new RequestHeaderRequestMatcher("Authorization")).addFilter(new JwtAuthorizationFilter(authenticationManager(), jwtUtil))
;
}
}
@Order(101)
@Configuration
@RequiredArgsConstructor
public static class AppSecuritySAML2 extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()).and()
.antMatcher("/**").authorizeRequests()
.antMatchers("/saml2/service-provider-metadata/**", "/idm-app/**").permitAll()
.antMatchers("/**").authenticated().and()
// This whole configuration will only be active, if the previous (100) didn't match
.saml2Login()
//...
;
}
}