I was updating current spring boot application version to spring boot 3, 3.4.4 to be precise, after updating the dependencies and checking out rest endpoints everything seems to be working fine, but actuator/health endpoint is giving me access denied 401. I tried to configuring securityFilter chain to permit health endpoint, but still no luck. What would be the issue here
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.core.annotation.Order;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationConverter;
import org.springframework.security.oauth2.server.resource.authentication.JwtGrantedAuthoritiesConverter;
import org.springframework.security.web.SecurityFilterChain;
@EnableWebSecurity
@ComponentScan("com.xxxx.nes.**")
@EntityScan("com.xxxx.nes.model.**")
@EnableJpaRepositories("com.xxxx.nes.model.**")
public class ResourceServeConfig {
@Bean
@Order(1)
public SecurityFilterChain actuatorEndpoints(HttpSecurity http) throws Exception {
http
.securityMatcher("/nes/actuator/health")
.authorizeHttpRequests(auth -> auth.anyRequest().permitAll())
.csrf(AbstractHttpConfigurer::disable);
return http.build();
}
@Bean
@Order(2)
public SecurityFilterChain securedEndpoints(HttpSecurity http) throws Exception {
http
.csrf(csrf -> csrf.ignoringRequestMatchers("/**/notifications/**"))
.authorizeHttpRequests(
auth ->
auth
.requestMatchers("/**/notifications/**")
.hasAuthority("SCOPE_notifications")
.anyRequest()
.authenticated()
)
.oauth2ResourceServer(
oauth -> oauth.jwt(jwt -> jwt.jwtAuthenticationConverter(jwtAuthenticationConverter()))
);
return http.build();
}
private JwtAuthenticationConverter jwtAuthenticationConverter() {
JwtGrantedAuthoritiesConverter converter = new JwtGrantedAuthoritiesConverter();
converter.setAuthorityPrefix("SCOPE_");
converter.setAuthoritiesClaimName("scope");
JwtAuthenticationConverter jwtConverter = new JwtAuthenticationConverter();
jwtConverter.setJwtGrantedAuthoritiesConverter(converter);
return jwtConverter;
}
}
and application.yaml
application:
name: nes
datasource:
url: ${nes.db.jdbc.url}
username: ${nes.db.username}
password: ${nes.db.password}
driverClassName: ${nes.db.driverClassName:com.mysql.cj.jdbc.Driver}
jpa:
hibernate:
ddl-auto: none
naming:
physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
database: mysql
database-platform: ${nes.jpa.hibernate.dialect}
liquibase:
enabled: ${nes.db.liquibase.enabled:true}
contexts: ${nes.db.liquibase.contexts:none}
user: ${nes.db.liquibase.user}
password: ${nes.db.liquibase.password}
security:
oauth2:
resourceserver:
jwt:
issuer-uri: ${nes.security.oauth2.resourceserver.jwt.issuer-uri}
server:
port: ${nes.server.port}
servlet:
context-path: ${nes.server.context-path:/nes}
compression:
enabled: ${nes.server.compression.enabled:true}
management:
endpoints:
web:
exposure:
include: health
endpoint:
health:
show-details: never
show-components: never
security:
aws:
region: ${nes.security.aws.region}
ses:
atp:
queue:
url: ${nes.ses.atp.queue.url}
logging:
level:
org.hibernate.SQL: DEBUG
org.hibernate.type.descriptor.sql.BasicBinder: TRACE
Needed to add @Configuration annotation then matching started to hit to custom filterchain
@EnableWebSecurity
@ComponentScan("com.xxxx.nes.**")
@EntityScan("com.xxxx.nes.model.**")
@EnableJpaRepositories("com.xxxx.nes.model.**")
@Configuration <---
public class ResourceServeConfig {
@Bean
@Order(1)
public SecurityFilterChain actuatorEndpoints(HttpSecurity http) throws Exception {
http
.securityMatcher("/actuator/health")
.authorizeHttpRequests(auth -> auth.anyRequest().permitAll())
.csrf(AbstractHttpConfigurer::disable);
return http.build();
}
@Bean
@Order(2)
public SecurityFilterChain securedEndpoints(HttpSecurity http) throws Exception {
http
.csrf(csrf -> csrf.ignoringRequestMatchers("/**/notifications/**"))
.authorizeHttpRequests(
auth ->
auth
.requestMatchers("/**/notifications/**")
.hasAuthority("SCOPE_notifications")
.anyRequest()
.authenticated()
)
.oauth2ResourceServer(
oauth -> oauth
.jwt(jwt -> jwt.jwtAuthenticationConverter(jwtAuthenticationConverter()))
);
return http.build();
}
private JwtAuthenticationConverter jwtAuthenticationConverter() {
JwtGrantedAuthoritiesConverter converter = new JwtGrantedAuthoritiesConverter();
converter.setAuthorityPrefix("SCOPE_");
converter.setAuthoritiesClaimName("scope");
JwtAuthenticationConverter jwtConverter = new JwtAuthenticationConverter();
jwtConverter.setJwtGrantedAuthoritiesConverter(converter);
return jwtConverter;
}
}