For our application we had to write a custom OIDCUserService and OIDCUser objects as well as customize Azure's AAD Security Config with Spring.
Here is the code for Spring Boot 2.6 that works.
@EnableWebSecurity
class AADServerConfig {
@Order(1)
@Configuration
static class ApiWebSecurityConfigurationAdapter extends AadResourceServerWebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
super.configure(http)
http
.cors()
.and()
.csrf().disable()
.antMatcher("/api/**")
.authorizeRequests().anyRequest().authenticated()
http
.headers()
.frameOptions()
.disable()
.httpStrictTransportSecurity()
.disable()
}
}
@Configuration
class HtmlWebSecurityConfigurerAdapter extends AadWebSecurityConfigurerAdapter {
@Autowired
private OAuth2AuthenticationSuccessHandler oAuth2AuthenticationSuccessHandler;
@Autowired
private OAuth2AuthenticationFailureHandler oAuth2AuthenticationFailureHandler;
@Autowired
private OAuth2HttpCookieAuthorizationRequestRepository oAuth2HttpCookieAuthorizationRequestRepository;
@Override
protected void configure(HttpSecurity http) throws Exception {
super.configure(http)
http
.oauth2Login()
.authorizationEndpoint()
.authorizationRequestRepository(oAuth2HttpCookieAuthorizationRequestRepository)
.and()
.successHandler(oAuth2AuthenticationSuccessHandler)
.failureHandler(oAuth2AuthenticationFailureHandler)
http
.cors()
.and()
.csrf().disable()
.authorizeRequests()
.antMatchers("/", "/login", "/*.js", "/*.css", "/token", "/actuator/**", "/actuator/prometheus", "/version/**", "/docusign/events/**").permitAll()
.anyRequest().authenticated()
http
.headers()
.frameOptions()
.disable()
.httpStrictTransportSecurity()
.disable()
}
}
@Bean
CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration cors = new CorsConfiguration()
cors.setAllowedOrigins([
"http://localhost:3000",
"http://localhost:3001",
"http://localhost:8080",
"https://localhost:8080",
"https://dev-local.panoram.co"
])
cors.setAllowedMethods(Arrays.asList("POST", "GET", "PUT", "HEAD", "DELETE", "OPTIONS", "FETCH", "PATCH"))
cors.setAllowCredentials(true)
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource()
source.registerCorsConfiguration("/**", cors.applyPermitDefaultValues())
return source
}
}
All fine and good. We now upgrade to Spring Boot 3.x and Azure 5.4 and here is the code like above, but refactored to match the new way to config Spring Security etc. Now CORS is not working. The big difference I see is before we extended AadResourceServerWebSecurityConfigurerAdapter in 2.6 but that no longer exists in Azure 5.4 and we have to use AadResourceServerHttpSecurityConfigurer.
@EnableWebSecurity
class AADServerConfig {
@Order(1)
@Configuration
//com.azure.spring.cloud.autoconfigure.aad.AadResourceServerWebSecurityConfigurerAdapter
class ApiWebSecurityConfigurationAdapter extends AadResourceServerHttpSecurityConfigurer {
@Override
void configure(HttpSecurity http) throws Exception {
super.configure(http)
http
.cors(corsCustomizer -> {
corsCustomizer.configurationSource(corsConfigurationSource())
})
.csrf(csrfConfig -> {
csrfConfig.disable()
})
.securityMatcher("/api/**")
.authorizeHttpRequests {}(requestsCustomizer -> {
requestsCustomizer.anyRequest().authenticated()
})
http
.headers(header -> {
header.frameOptions {frameOptions -> {
frameOptions.disable()
}}
header.httpStrictTransportSecurity {transportConfig ->
transportConfig.disable()
}
})
}
}
@Configuration
class HtmlWebSecurityConfigurerAdapter extends AadWebApplicationHttpSecurityConfigurer {
@Autowired
private OAuth2AuthenticationSuccessHandler oAuth2AuthenticationSuccessHandler;
@Autowired
private OAuth2AuthenticationFailureHandler oAuth2AuthenticationFailureHandler;
@Autowired
private OAuth2HttpCookieAuthorizationRequestRepository oAuth2HttpCookieAuthorizationRequestRepository;
@Override
void configure(HttpSecurity http) throws Exception {
super.configure(http)
http
.oauth2Login(customizer -> {
customizer.authorizationEndpoint {endpointConfig -> {
endpointConfig.authorizationRequestRepository(oAuth2HttpCookieAuthorizationRequestRepository)
}}
customizer.successHandler {oAuth2AuthenticationSuccessHandler}
customizer.failureHandler {oAuth2AuthenticationFailureHandler}
})
http
.cors(corsCustomizer -> {
corsCustomizer.configurationSource(corsConfigurationSource())
})
.csrf(csrfConfig -> {
csrfConfig.disable()
})
.authorizeHttpRequests(authz ->{
authz.requestMatchers("/", "/login", "/*.js", "/*.css", "/token", "/actuator/**", "/actuator/prometheus", "/version/**", "/docusign/events/**").permitAll()
.anyRequest().authenticated()
})
http.headers(header -> {
header.frameOptions {frameOptions -> {
frameOptions.disable()
}}
header.httpStrictTransportSecurity {transportConfig ->
transportConfig.disable()
}
})
}
}
@Bean
CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration()
configuration.setAllowedOrigins(Arrays.asList("http://localhost:3000",
"https://localhost:3000",
"http://localhost:3001",
"https://localhost:3001",
"https://localhost:5001",
"http://localhost:5001",
"http://localhost:8080",
"https://localhost:8080",
"https://dev-local.panoram.co"))
configuration.setAllowedMethods(Arrays.asList("POST", "GET", "PUT", "HEAD", "DELETE", "OPTIONS", "FETCH", "PATCH"))
configuration.setAllowCredentials(true)
CorsConfigurationSource source = new UrlBasedCorsConfigurationSource()
source.registerCorsConfiguration("/**", configuration.applyPermitDefaultValues())
return source
}
}
I've spent about 2 weeks trying to get CORS to work again, but no luck. What am I doing wrong?
AadResourceServerHttpSecurityConfigurer
doesn't support the configure
method, could you try like this:
class ApiWebSecurityConfig {
@Bean
SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.apply(AadWebApplicationHttpSecurityConfigurer.aadWebApplication())
...
return http.build();
}
}
class HtmlWebSecurityConfig {
@Bean
public SecurityFilterChain htmlFilterChain(HttpSecurity http) throws Exception {
http.apply(AadWebApplicationHttpSecurityConfigurer.aadWebApplication())
...
return http.build();
}
}
Please refer to https://learn.microsoft.com/en-us/azure/developer/java/spring-framework/spring-security-support?tabs=SpringCloudAzure5x#spring-security-with-azure-active-directory for more info.