Given I created a custom JWT decoder as described in the Spring OAuth2 Resource Server Documentation with NimbusJwtDecoder.

Example:

  @Bean
  public JwtDecoder getJwtDecoder() throws ParseException {
        NimbusJwtDecoder jwtDecoder =  NimbusJwtDecoder
              .withJwkSetUri(this.properties.getJwkSetUri())
              .jwsAlgorithms(algorithms -> {
                  algorithms.add(SignatureAlgorithm.ES256);
                  algorithms.add(SignatureAlgorithm.ES384);
                  algorithms.add(SignatureAlgorithm.ES512);
              })
              .build();
        jwtDecoder.setJwtValidator(this.getTokenValidator());
        return jwtDecoder
  }

And I configure my Spring App as Oauth2 Resource Server, like:

@EnableWebSecurity
@Configuration
public class SecurityConfig {

    @Bean
    public SecurityFilterChain oauth2FilterChain(HttpSecurity http) throws Exception {
        http
            .csrf(AbstractHttpConfigurer::disable)
            .authorizeHttpRequests(authorize -> authorize
                    .requestMatchers("/api/v1/**").authenticated()
            )
            .oauth2ResourceServer(oauth2 -> oauth2
                    .jwt(Customizer.withDefaults()));

        return http.build();
    }
}

When I send a request to /api/v1/** with a JWT token that has a malformed JWT header

POST /api/v1/test HTTP/1.1
Host: localhost:80
Authorization: Bearer <MELFORMED_HEADER>.<PAYLOAD>.<SIGNATURE>

Expected Behavior Then I expect that a 401 is responded with a www-authenticate header which doesn't expose any app internal information.

Something like:

www-authenticate: Bearer error="invalid_token", error_description="An error occurred while attempting to decode the Jwt: Invalid unsecured/JWS/JWE", error_uri="https://tools.ietf.org/html/rfc6750#section-3.1"

Current Behavior Then currently a 401 is responded with a www-authenticate header which does expose that the app is using a Nimbusdecoder.

www-authenticate: Bearer error="invalid_token", error_description="An error occurred while attempting to decode the Jwt: Invalid unsecured/JWS/JWE header: Invalid JSON: com.nimbusds.jose.shaded.gson.stream.MalformedJsonException: Unterminated string at line 1 column 23 path $.", error_uri="https://tools.ietf.org/html/rfc6750#section-3.1"

Context How has this issue affected you? I am not sure if this is a security breach, but at least I expect, that my client is not bothered with server-internal information.

What are you trying to accomplish? Provide my clients with a clean API without exposing any server-internal details.

Comment From: jzheaux

Thanks, @akamom.

With other ParseExceptions in NimbusJwtDecoder, Spring Security drops Nimbus's error message and replaces it with "Malformed payload". I think it's a good idea to be consistent here and remove the information from the error message.

Are you able to submit a PR that catches the ParseException that JWTParser#parse throws and drop the Nimbus error message? You can see an example in the same file of what I'm talking about in NimbusJwtDecoder#processJwt:

catch (Exception ex) {
    this.logger.trace(...)
    if (ex.getCause() instanceof ParseException) {
        throw new BadJwtException(String.format(DECODING_ERROR_MESSAGE_TEMPLATE, "Malformed payload"), ex);
    }
    throw new BadJwtException(String.format(DECODING_ERROR_MESSAGE_TEMPLATE, ex.getMessage()), ex);
}

If so, please base the PR off of 5.8.x, and once it's merged, I'll forward-port it to the other branches.

Comment From: madhu-kommula

Hello, We are facing the same issue with NimbusReactiveJwtDecoder. Can the same fix be applied to the reactive world as well?