Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

After upgraded to Spring Boot 3.0.0 from 2.7.6, public API are not accessible.

@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
    return http
        .csrf(CsrfConfigurer::disable)
        .authorizeHttpRequests(requests -> requests
            .anyRequest().authenticated())
            .oauth2ResourceServer(OAuth2ResourceServerConfigurer::jwt)
            .build();
@Bean
public WebSecurityCustomizer webSecurityCustomizer() {
    return web -> web
                     .ignoring()
                         .requestMatchers(CorsUtils::isPreFlightRequest)    
                         .requestMatchers("/actuator/**", "/graphiql/**", "/voyager/**", "/vendor/**", "/rest/**",
                             "/swagger-ui/**", "/v3/api-docs/**");

You are almost there: move requestMatchers with permitAll to SecurityFilterChain definition (and remove WebSecurityCustomizer):

@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
    return http.csrf(CsrfConfigurer::disable)
        .authorizeHttpRequests(requests -> requests
            .requestMatchers("/resources/**", "/signup", "/about").permitAll() 
            .anyRequest().authenticated())
        .oauth2ResourceServer(OAuth2ResourceServerConfigurer::jwt)
        .build();

Also, make sure the configuration class containing your SecurityFilterChain bean declaration is decorated with @Configuration (set a breakpoint or log line to ensure it is instantiated).

Few notes:

  • never disable CSRF protection if you don't also disable sessions with http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
  • CORS is configured with SecurityFilterChain too: http.cors().configurationSource(corsConfigurationSource())
  • you might need to map roles or groups or whatever your authorization-server populates as private-claim to Spring authorities by providing your own jwtAuthenticationConverter to JWT oauth2ResourceServer configurer
  • You can do all of above with no Java conf (just a few properties) with thin wrappers around spring-boot-starter-oauth2-resource-server I wrote:

    <dependency>
        <groupId>com.c4-soft.springaddons</groupId>
        <artifactId>spring-addons-webmvc-jwt-resource-server</artifactId>
        <version>6.0.9</version>
    </dependency>
    
    @Configuration
    @EnableMethodSecurity
    public static class SecurityConfig {
    
    com.c4-soft.springaddons.security.issuers[0].location=https://localhost:8443/realms/master
    # This is adapted to Keycloak with a client-id spring-addons-public. Replace with the claim(s) your authorization-server puts roles into
    com.c4-soft.springaddons.security.issuers[0].authorities.claims=realm_access.roles,resource_access.spring-addons-public.roles
    # you might want something more restrictive as allowed origins (accepts a list), at least for a part of your endpoints
    com.c4-soft.springaddons.security.cors[0].path=/**
    com.c4-soft.springaddons.security.cors[0].allowed-origins=*
    

    Complete (short) tutorials there (with spring libs only or "my" wrappers): https://github.com/ch4mpy/spring-addons/tree/master/samples/tutorials

    Added .requestMatchers("/resources/**", "/signup", "/about").permitAll() still getting unauthorised error. – Thirumal Dec 24, 2022 at 15:15 Last, check that your security conf is loaded (set a breakpoint or a log line). Maybe you just forgot to decorate your configuration class with @Configuration. – ch4mp Dec 25, 2022 at 0:05 // ... .authorizeHttpRequests(authorize -> authorize .requestMatchers("/resources/**", "/signup", "/about").permitAll() .requestMatchers("/admin/**").hasRole("ADMIN") .requestMatchers("/db/**").access(new WebExpressionAuthorizationManager("hasRole('ADMIN') and hasRole('DBA')")) // .requestMatchers("/db/**").access(AuthorizationManagers.allOf(AuthorityAuthorizationManager.hasRole("ADMIN"), AuthorityAuthorizationManager.hasRole("DBA"))) .anyRequest().denyAll() return http.build();

    Provided of https://docs.spring.io/spring-security/reference/servlet/authorization/authorize-http-requests.html

    EDIT : To complete my answer, you have access to all methods, so to set up a resource server you need to add this :

    @Bean
    SecurityFilterChain web(HttpSecurity http) throws Exception {
            // ...
            .authorizeHttpRequests(authorize -> authorize                                  
                // ...                                                
            .and()
            .oauth2ResourceServer( OAuth2ResourceServerConfigurer::jwt )
        return http.build();
    

    Remember to add the variables corresponding to your OAuth2 provider

    spring.security.oauth2.resourceserver.jwt.issuer-uri=https://{your-ouath2-provider}/{issuer-uri}
    spring.security.oauth2.resourceserver.jwt.jwk-set-uri=https://{your-ouath2-provider}/{jwk-uri} (optionnal)
    

    The links depend on your oauth2 provider.

    For more information about the resource owner server : https://docs.spring.io/spring-security/reference/servlet/oauth2/resource-server/index.html

    Thanks for contributing an answer to Stack Overflow!

    • Please be sure to answer the question. Provide details and share your research!

    But avoid

    • Asking for help, clarification, or responding to other answers.
    • Making statements based on opinion; back them up with references or personal experience.

    To learn more, see our tips on writing great answers.