spring-projects/spring-security · error · HttpMessageNotReadableException

An error occurred reading the OAuth 2.0 Access Token…

Error message

An error occurred reading the OAuth 2.0 Access Token Response: ${ex.getMessage()}

What it means

OAuth2AccessTokenResponseHttpMessageConverter.readInternal wraps any failure while reading/parsing the token endpoint HTTP response into an HttpMessageNotReadableException whose message includes the original exception message. Typical underlying causes are JSON parse failures or the converter rejecting the payload (e.g. missing access_token).

Solutions

  1. Log/inspect the underlying exception and raw body: enable wire-level logging for the token request to see what the server actually returned
  2. Verify the token-uri points at the JSON token endpoint and that no proxy/SSO intercepts the call
  3. Check the response Content-Type is application/json and the provider returns a spec-compliant body
  4. If the provider's body deviates (e.g. errors with 200), plug in a custom access token response converter

Example fix

// before
# token-uri pointing at authorize endpoint
provider.myidp.token-uri: https://idp.example.com/authorize
// after
provider.myidp.token-uri: https://idp.example.com/oauth2/token
Defensive patterns

Strategy: try-catch

Try / catch

try {
    OAuth2AccessTokenResponse r = converter.convert(inputMessage);
} catch (HttpMessageNotReadableException e) {
    // log e.getCause() and the raw body to see what the token endpoint returned
}

Prevention

When it happens

Trigger: Token endpoint returns non-JSON (HTML login/error page, empty body), malformed JSON, or a JSON body the DefaultMapOAuth2AccessTokenResponseConverter rejects — then readInternal converts the exception.

Common situations: Wrong token-uri pointing to an HTML page; gateway/SSO intercepting and returning an error page; provider sending text/plain content type the JSON converter refuses; missing access_token in an otherwise-200 response.

Understand the failure class

Background: "Invalid JSON response" and "Failed to parse response" errors: when an API answers 200 but the body isn't the JSON your library expected — this error's family across 28 libraries.

Related errors


AI-assisted analysis of spring-projects/spring-security@96852e8860 (2026-09-10). Data as JSON: /api/errors/99e7ceb469fcfdd6. Report an issue: GitHub.

Appendix: source

Thrown at oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/http/converter/OAuth2AccessTokenResponseHttpMessageConverter.java:83

		this.jsonMessageConverter = converter;
	}

	@Override
	protected boolean supports(Class<?> clazz) {
		return OAuth2AccessTokenResponse.class.isAssignableFrom(clazz);
	}

	@Override
	@SuppressWarnings("unchecked")
	protected OAuth2AccessTokenResponse readInternal(Class<? extends OAuth2AccessTokenResponse> clazz,
			HttpInputMessage inputMessage) throws HttpMessageNotReadableException {
		try {
			Map<String, Object> tokenResponseParameters = (Map<String, Object>) this.jsonMessageConverter
				.read(STRING_OBJECT_MAP.getType(), null, inputMessage);
			return this.accessTokenResponseConverter.convert(tokenResponseParameters);
		}
		catch (Exception ex) {
			throw new HttpMessageNotReadableException(
					"An error occurred reading the OAuth 2.0 Access Token Response: " + ex.getMessage(), ex,
					inputMessage);
		}
	}

	@Override
	protected void writeInternal(OAuth2AccessTokenResponse tokenResponse, HttpOutputMessage outputMessage)
			throws HttpMessageNotWritableException {
		try {
			Map<String, Object> tokenResponseParameters = this.accessTokenResponseParametersConverter
				.convert(tokenResponse);
			this.jsonMessageConverter.write(tokenResponseParameters, STRING_OBJECT_MAP.getType(),
					MediaType.APPLICATION_JSON, outputMessage);
		}
		catch (Exception ex) {
			throw new HttpMessageNotWritableException(
					"An error occurred writing the OAuth 2.0 Access Token Response: " + ex.getMessage(), ex);
		}

View on GitHub (pinned to 96852e8860)