lilalinux
lilalinux

Reputation: 3031

JWT authentication with fallback to SAML2 for the same path

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.

Upvotes: 2

Views: 1505

Answers (1)

lilalinux
lilalinux

Reputation: 3031

The solution is to

  1. Duplicate the configuration with @Order and
  2. 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()
                    //...
            ;
        }
    }
    

Upvotes: 3

Related Questions