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:
- On click of https://localhost:8088/my_app/ API application should redirect to OKTA login page and then get the user name in response.
- Based on username generate JWT token.
- 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;
}
}
}