Skip to content

OAuth2 RefreshTokenAuthenticationConverter fails to refresh token in Spring Security OAuth2 Authorization Server 1.4.2 #16855

Open
@XiaoHDZXF

Description

@XiaoHDZXF

Description

After upgrading from Spring Boot 2.x to Spring Boot 3.x with JDK 17, I encountered an issue with the OAuth2 refresh token functionality. The token refresh operation fails because of a significant change in how request parameters are processed in the newer version of Spring Security OAuth2 Authorization Server.

Problem Details

The issue occurs in OAuth2RefreshTokenAuthenticationConverter#convert method. In version 1.4.2, the implementation uses OAuth2EndpointUtils.getFormParameters() instead of the previous OAuth2EndpointUtils.getParameters() method, which has a different implementation logic:

Previous implementation (0.4.2):

static MultiValueMap<String, String> getParameters(HttpServletRequest request) {
    Map<String, String[]> parameterMap = request.getParameterMap();
    MultiValueMap<String, String> parameters = new LinkedMultiValueMap<>(parameterMap.size());
    parameterMap.forEach((key, values) -> {
       if (values.length > 0) {
          for (String value : values) {
             parameters.add(key, value);
          }
       }
    });
    return parameters;
}

Current implementation (1.4.2):

static MultiValueMap<String, String> getFormParameters(HttpServletRequest request) {
    Map<String, String[]> parameterMap = request.getParameterMap();
    MultiValueMap<String, String> parameters = new LinkedMultiValueMap<>();
    parameterMap.forEach((key, values) -> {
        String queryString = StringUtils.hasText(request.getQueryString()) ? request.getQueryString() : "";
        // If not query parameter then it's a form parameter
        if (!queryString.contains(key) && values.length > 0) {
            for (String value : values) {
                parameters.add(key, value);
            }
        }
    });
    return parameters;
}

Root Cause

The new implementation attempts to distinguish between query parameters and form parameters by checking if the parameter key exists in the query string. However, this causes a critical issue:

If the request's query string contains the same parameters as the parameter map (which can happen when parameters are sent in the URL rather than in the request body), the parameters MultiValueMap will be empty. As a result, String grantType = parameters.getFirst(OAuth2ParameterNames.GRANT_TYPE) returns null, causing the refresh token operation to fail.

Environment

  • Spring Boot: 3.x
  • Spring Security OAuth2 Authorization Server: 1.4.2
  • JDK: 17

Expected Behavior

The refresh token functionality should work regardless of how the parameters are sent (query string or form body).

Possible Solution

Consider revising the getFormParameters method to properly handle cases where parameters might be present in both the query string and form body, or provide a more robust way to extract the required parameters for token refresh operations.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions