javaspring-bootauth0spring-boot-security

Spring Boot 3.3.2 with Spring Security 6.3.1 issue (no support of auth0-spring-security-api with Spring Framework 3.3.2)


I am to trying upgrade my project to Spring Boot 3.3.2 version and the Spring Security version is 6.3.1.

In the code, the JwtWebSecurityConfigurer class is used to set the below fields.

JwtWebSecurityConfigurer
        .forRS256(env.getRequiredProperty("AUTH0_API_AUDIENCE"), 
         env.getRequiredProperty("AUTH0_API_ISSUER"))
        .configure(http);

The package com.auth0.spring.security.api.JwtWebSecurityConfigurer is used and it is derived from dependency:

<dependency>
    <groupId>com.auth0</groupId>
    <artifactId>auth0-spring-security-api</artifactId>
    <version>1.5.3</version>
</dependency>

The problem is I cannot use auth0-spring-security-api with Spring Framework 3.3.2 because it is not compatible. I would like to know the equivalent library to use instead of auth0-spring-security-api along with Spring framework 3.3.2.

I am getting the below error:

[http-nio-8082-exec-4] ERROR [dispatcherServlet] - Servlet.service() for servlet 
  [dispatcherServlet] threw exception
   java.lang.NoSuchMethodError: 'javax.servlet.http.HttpServletRequest 
  org.springframework.security.web.context.HttpRequestResponseHolder.getRequest()'
 atcom.auth0.spring.security.api.BearerSecurityContextRepository.loadContext(BearerSecurityContextRepository.java:21)
at org.springframework.security.web.context.SecurityContextRepository.lambda$loadDeferredContext$0(SecurityContextRepository.java:81)


Solution

    1. Instead of using the auth0 library which is not compatible with Spring Boot 3.3.2 with Spring Security 6.3.1 issue , the spring boot libraries are used.

    Old dependency:

    <dependency>
        <groupId>com.auth0</groupId>
        <artifactId>auth0-spring-security-api</artifactId>
        <version>1.5.3</version>
    </dependency>
    

    Replaced dependency:

            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-security</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
            </dependency>
    
    1. JwtWebSecurityConfigurer .forRS256(env.getRequiredProperty("AUTH0_API_AUDIENCE"), env.getRequiredProperty("AUTH0_API_ISSUER")) .configure(http);

    is replaced with

        http.oauth2ResourceServer(oauth2 -> oauth2.jwt(jwt -> jwt.decoder(jwtDecoder())))
    
    OAuth2TokenValidator<Jwt> audienceValidator() {
            return new AudienceValidator();
        }
    
        @Bean
        JwtDecoder jwtDecoder() {
            NimbusJwtDecoder jwtDecoder = (NimbusJwtDecoder) JwtDecoders
                    .fromIssuerLocation(env.getProperty("AUTH0_API_ISSUER"));// issuer name
    
            OAuth2TokenValidator<Jwt> audienceValidator = audienceValidator();
    
            OAuth2TokenValidator<Jwt> withIssuer = JwtValidators.createDefaultWithIssuer(env.getProperty("AUTH0_API_ISSUER"));
            OAuth2TokenValidator<Jwt> withAudience = new DelegatingOAuth2TokenValidator<>(withIssuer, audienceValidator);
    
            jwtDecoder.setJwtValidator(withAudience);
    
            return jwtDecoder;
        }
    
        class AudienceValidator implements OAuth2TokenValidator<Jwt> {
            OAuth2Error error = new OAuth2Error("custom_code", "Custom error message", null);
    
            @Override
            public OAuth2TokenValidatorResult validate(Jwt jwt) {
                if (jwt.getAudience().contains(env.getRequiredProperty("AUTH0_API_AUDIENCE"))) {
                    return OAuth2TokenValidatorResult.success();
                } else {
                    return OAuth2TokenValidatorResult.failure(error);
                }
            }
        }
    
    1. Application.properties is set with

      spring.boot.security.oauth2.resourceserver.jwt.issuer-uri = issueruri spring.boot.security.oauth2.resourceserver.jwt.audiences = audience spring.boot.security.oauth2.resourceserver.jwt.jws-algorithms = RS512 spring.mvc.pathmatch.matching-strategy = ANT_PATH_MATCHER

    4.Also the antMatchers are replaced withrequestMatchers

    http
                    .sessionManagement(sessionManagement -> sessionManagement
                            .sessionCreationPolicy(SessionCreationPolicy.STATELESS))
                    .csrf(AbstractHttpConfigurer::disable)
                    .oauth2ResourceServer(oauth2 -> oauth2.jwt(jwt -> jwt.decoder(jwtDecoder())))
                    .authorizeHttpRequests(authorizeRequests -> authorizeRequests
                            .requestMatchers("/requests")
                            .hasAuthority(API_REQUEST_READ_AUDIENCE).requestMatchers("/v1.0/**")
                            .authenticated())
    
    1. After getting 403 Forbidden issue with **WWW- Autheticate Bearer error="insufficient_scope", error_description="The request requires higher privileges than provided by the access token."**, the changes are made in to add the "SCOPE_"

      http.authorizeHttpRequests(authorizeRequests -> authorizeRequests.requestMatchers("/requests").hasAuthority("SCOPE_"+API_REQUEST_READ_AUDIENCE)

    Now the application is upgraded with Spring Boot 3.3.2 with Spring Security 6.3.1 issue. The crucial part is to understand the Spring security flow as given in https://docs.spring.io/spring-security/reference/servlet/oauth2/resource-server/jwt.html