how to integrate Spring Boot application with Both SAML and JWT token: Multiple WebSecurityConfigurerAdapter
Asked Answered
A

0

6

I am trying to use both JWT token and SAML in my spring boot application. My application creates JWT token using a username returned from OKTA.

Flow:

  1. On click of https://localhost:8088/my_app/ API application should redirect to OKTA login page and then get the user name in response.
  2. Based on username generate JWT token.
  3. Use the JWT token for the remaining APIS authentication.

I am able to navigate the application to the OKTA login page, authenticate the user and get the user name. Then after this step, I am trying to create a JWT token using this username.

The problem I am facing is , since I have two WebSecurityConfigurerAdapter one is for SAML redirect and another is for JWT I am not able to restrict the APIS to have JWT token. My application is not checking all APIS for JWT token.

When I disable SAML, JWT works, if I disable JWT SAML works fine. Now can someone please tell me how can I configure my application to use both SAML and JWT web security configs?

@Confguration
@EnableWebSecurity
public class SecurityConfig {
    @Order(1)
    @Configuration
    public static class SAMLConfig extends WebSecurityConfigurerAdapter {
        @Autowired
        private SAMLUserDetailsServiceImpl samlUserDetailsServiceImpl;
        @Value("${security.saml2.metadata-url}")
        String metadataUrl;
        @Value("${server.ssl.key-alias}")
        String keyAlias;
        @Value("${server.ssl.key-store-password}")
        String password;
        @Value("${server.port}")
        String port;
        @Value("${server.ssl.key-store}")
        String keyStoreFilePath;

        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.requestMatchers()
                    .antMatchers("/saml*").and()
                    .apply(saml())
                    .serviceProvider()
                    .keyStore()
                    .storeFilePath(this.keyStoreFilePath)
                    .password(this.password)
                    .keyname(this.keyAlias)
                    .keyPassword(this.password)
                    .and()
                    .protocol("https")
                    .hostname(String.format("%s:%s", "localhost", this.port))
                    .basePath("/my_app")
                    .and()
                    .identityProvider()
                    .metadataFilePath(this.metadataUrl);
        }

    }


    @Order(2)
    public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
        @Autowired
        private JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint;
        @Autowired
        private UserDetailsService jwtUserDetailsService;
        @Autowired
        private JwtRequestFilter jwtRequestFilter;

        @Autowired
        public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
            //encrypts user passweod so its not visible to outside world
            auth.userDetailsService(jwtUserDetailsService).passwordEncoder(passwordEncoder());
        }

        @Bean
        public PasswordEncoder passwordEncoder() {
            return new BCryptPasswordEncoder();
        }

        @Bean
        @Override
        public AuthenticationManager authenticationManagerBean() throws Exception {
            return super.authenticationManagerBean();
        }


        @Override
        protected void configure(HttpSecurity httpSecurity) throws Exception {


            httpSecurity.requestMatchers()
                    .antMatchers("/user/hello").and().authorizeRequests().anyRequest().authenticated().and().
                            exceptionHandling().authenticationEntryPoint(jwtAuthenticationEntryPoint).and().sessionManagement()
                    .sessionCreationPolicy(SessionCreationPolicy.STATELESS);
            httpSecurity.cors();
            httpSecurity.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class);

        }

        @Bean
        CorsConfigurationSource corsConfigurationSource() {
            UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
            source.registerCorsConfiguration("/**", new CorsConfiguration().applyPermitDefaultValues());
            return source;
        }


    }
}
Approval answered 20/10, 2020 at 12:42 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.