auth0-samples / auth0-spring-security5-api-sample

Sample demonstrating how to secure your API using Spring Boot 2 and Spring Security 5
MIT License
96 stars 67 forks source link

Spring Boot 3 and Spring Security 6 #25

Open jimmyjames opened 1 year ago

jimmyjames commented 1 year ago

For those using or upgrading to Spring Boot 3 with Spring Security 6, we will be either creating a new sample repo and corresponding quickstart article, or updating this sample and the existing quickstart. In the meantime, let's use this issue to discuss any issues and share tips that may help others.

Trying the upgrade to Spring Boot 3 myself, these are my findings which I hope will others:

Note The WIP changes can be found on the use-spring-6 branch.

Migrating to Spring Boot 3 and Spring Security 6 (Servlet)

Step 1 - Update to latest Spring Boot 3 and Spring Security 5.8

Note The following changes are captured in this commit.

As documented on the Spring Boot 3 Migration Guide, the first thing to do is update to the latest of Spring Boot 2 and use Spring Security 5.8. As shown in this commit, this involves updating your dependencies (gradle shown):

plugins {
    latest 
    id 'org.springframework.boot' version '2.7.8'
}

ext['spring-security.version']='5.8.1'

After doing this, you'll notice deprecation warnings regarding the authorizeRequests and mvcMatchers usage in the SecurityConfig. We can change this to use authorizeHttpRequests and use requestMatcher:

@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
    http
            .authorizeHttpRequests((authorize) -> authorize
                .requestMatchers("/api/public").permitAll()
                .requestMatchers("/api/private").authenticated()
                .requestMatchers("/api/private-scoped").hasAuthority("SCOPE_read:messages"))
              .cors().and()
              .oauth2ResourceServer((oauth2ResourceServer) ->
                      // works, but not as clear:
                      // oauth2ResourceServer.jwt());
                      oauth2ResourceServer.jwt(jwt -> jwt.decoder(jwtDecoder())));

    return http.build();
}

The application should now compile without warnings, and running it should demonstrate the protected endpoints.

Step 2 - Update to Spring Boot 3

Note The following changes are captured in this commit.

Now we can update to Spring Boot 3, which involves a few things:

Update to latest Gradle

Update your gradle version to the latest of v7. If you don't do this, you may encounter errors related to building a jar when trying to run.

./gradlew wrapper --gradle-version 7.6

Update dependencies and source level

Update your dependency to use spring boot 3 (and make sure to remove the Spring Security version override if you followed the step above!):

plugins {
    // ...
    id 'org.springframework.boot' version '3.0.2'
}

sourceCompatibility = '17'

Add @Configuration annotation to SecurityConfig

Make sure to add the @Configuration annotation to the SecurityConfig class. Not doing this will cause the custom jwtDecoder bean to not get injected (the annotation should probably have always been there, but something in Spring Boot 3 seems to have made it required).

@EnableWebSecurity

// Needed since Spring Security 6 (or Spring Boot 3)!
@Configuration
public class SecurityConfig {
   //...
}

Run with Java 17!

If you followed the above steps, you should be able to run the sample. Note that Spring Boot 3 requires Java 17, and the application will fail to start if using a non-compatible java runtime.

./gradlew clean bootRun

Migrating to Spring Boot 3 and Spring Security 6 (WebFlux)

Note The required updates for this sample can be found in this commit.

Updating the WebFlux usage for Spring Boot 3 appears to be a bit simpler, requiring the following:

After doing the above, you should be able to run the application using a Java 17 runtime and see that the APIs are protected based on their authorization requirements.

mraible commented 1 year ago

FWIW, I don't think you need @EnableWebSecurity anymore, just @Configuration. I sent an email to Rob Winch to confirm it's the same for Spring WebFlux.

jimmyjames commented 1 year ago

Testing it out, it appears both servlet and WebFlux work without @EnableSpringSecurity. I'll push a new commit to remove @EnableWebSecurity.

mraible commented 1 year ago

@jimmyjames Is there anything I can do to help move this along?