I’m introducing a security layer into my application so that some endpoints are protected via Okta.
I have currently already implemented Spring Security Oauth2 with Azure, in fact the login to my app is managed like this.
So what I want to do now is add a new authentication, but only to access specific endpoint after logging in. What I expect is that when I try to reach the secure endpoint I will be redirected to the okta login page. Once authenticated then I have to go back to my protected page.
I implemented security config as follows:
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
public class WebSecurityConfig {
@Configuration
@Order(1)
public static class AzureSecurityConfig extends WebSecurityConfigurerAdapter {
@Bean
@Qualifier("jwtDecoder")
public JwtDecoder jwtDecoder() {
return JwtDecoders.fromOidcIssuerLocation("https://sts.windows.net/my-azure-issuer/");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.cors(withDefaults())
.csrf().disable()
.httpBasic().disable()
.antMatcher("/login/**").authorizeRequests()
.anyRequest().authenticated()
.and()
.oauth2ResourceServer().jwt().decoder(jwtDecoder())
;
}
}
@Configuration
@Order(2)
public static class OktaSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.cors(withDefaults())
.csrf().disable()
.antMatcher("/protected/**")
.authorizeRequests()
.anyRequest().authenticated()
.and()
.oauth2Login()
.and()
.oauth2ResourceServer().jwt().decoder(oktaJwtDecoder());
}
@Bean
@Qualifier("oktaJwtDecoder")
public JwtDecoder oktaJwtDecoder() {
return JwtDecoders.fromOidcIssuerLocation("https://dev-my-okta-issuer.okta.com/oauth2/default");
}
}
//....
//Another configuration class...
//....
@Bean
public JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter() throws Exception {
Set<String> notFilterPaths = new HashSet<>();
Collections.addAll(notFilterPaths, PUBLIC_URLS);
notFilterPaths.add("/protected/**");
return new JwtAuthenticationTokenFilter(authenticationManagerBean(), notFilterPaths);
}
@Bean
public ApiLogFilter apiLogFilter() {
return new ApiLogFilter();
}
@Bean
CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins(Arrays.asList("*"));
configuration.setAllowedMethods(Arrays.asList("GET", "POST", "OPTIONS", "DELETE", "PUT", "PATCH"));
configuration.setAllowedHeaders(Arrays.asList("x-recaptcha-token", "Origin", "Content-Type", "Accept", "Authorization", "Access-Control-Request-Method", "Access-Control-Request-Headers", "Access-Control-Allow-Origin"));
configuration.addExposedHeader("Access-Control-Allow-Origin");
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
}
}
but when I try to access the secure endpoint, I get the following error:
Bearer error="invalid_token", error_description="An error occurred while attempting to decode the Jwt: Signed JWT rejected: Another algorithm expected, or no matching key(s) found", error_uri="https://tools.ietf.org/html/rfc6750#section-3.1"
I can see from the logs instead:
14:05:52.780 JwtAuthenticationProvider - Failed to authenticate since the JWT was invalid
I understand that the jwt used for the protected endpoint call is actually the one used for all other calls in my app and is not valid for Okta. I separated the jwt decoders hoping that this would be correct but it didn’t solve the problem.
How can I solve it?
3