spring-projects/spring-security · error · HttpMessageNotReadableException

An error occurred reading the OAuth 2.0 Device Authorization

Error message

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

What it means

This HttpMessageNotReadableException is thrown by OAuth2DeviceAuthorizationResponseHttpMessageConverter.readInternal when the JSON device authorization response from the authorization server cannot be converted into an OAuth2DeviceAuthorizationResponse. It wraps any exception (parse error, missing required parameters like device_code or verification_uri, type mismatches) produced by the JSON message converter or the parameter converter. The original cause message is appended for diagnosis.

Source

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

	}

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

	@Override
	@SuppressWarnings("unchecked")
	protected OAuth2DeviceAuthorizationResponse readInternal(Class<? extends OAuth2DeviceAuthorizationResponse> clazz,
			HttpInputMessage inputMessage) throws HttpMessageNotReadableException {

		try {
			Map<String, Object> deviceAuthorizationResponseParameters = (Map<String, Object>) this.jsonMessageConverter
				.read(STRING_OBJECT_MAP.getType(), null, inputMessage);
			return this.deviceAuthorizationResponseConverter.convert(deviceAuthorizationResponseParameters);
		}
		catch (Exception ex) {
			throw new HttpMessageNotReadableException(
					"An error occurred reading the OAuth 2.0 Device Authorization Response: " + ex.getMessage(), ex,
					inputMessage);
		}
	}

	@Override
	protected void writeInternal(OAuth2DeviceAuthorizationResponse deviceAuthorizationResponse,
			HttpOutputMessage outputMessage) throws HttpMessageNotWritableException {

		try {
			Map<String, Object> deviceAuthorizationResponseParameters = this.deviceAuthorizationResponseParametersConverter
				.convert(deviceAuthorizationResponse);
			this.jsonMessageConverter.write(deviceAuthorizationResponseParameters, STRING_OBJECT_MAP.getType(),
					MediaType.APPLICATION_JSON, outputMessage);
		}
		catch (Exception ex) {
			throw new HttpMessageNotWritableException(
					"An error occurred writing the OAuth 2.0 Device Authorization Response: " + ex.getMessage(), ex);

View on GitHub (pinned to 96852e8860)

Solutions

  1. Log the wrapped cause (ex.getCause()) to see the actual conversion failure.
  2. Verify the device authorization endpoint URL returns application/json per RFC 8628.
  3. Check the response contains required parameters: device_code, verification_uri (and expires_in/user_code as configured).
  4. Inspect for a proxy/gateway rewriting the response body (HTML error pages).
  5. Set the converter's jsonMessageConverter (MappingJackson2HttpMessageConverter) so Jackson is on the classpath and configured.

Example fix

// before
OAuth2DeviceAuthorizationResponse response = converter.read(OAuth2DeviceAuthorizationResponse.class, inputMessage); // may throw
// after
try {
    OAuth2DeviceAuthorizationResponse response = converter.read(OAuth2DeviceAuthorizationResponse.class, inputMessage);
} catch (HttpMessageNotReadableException ex) {
    logger.error("Device authorization response read failed", ex.getCause());
    throw ex;
}
Defensive patterns

Strategy: try-catch

Validate before calling

if (!contentTypeCompatible(MediaType.APPLICATION_JSON)) {
    throw new IllegalArgumentException("Device authorization response must be JSON");
}

Try / catch

try {
    OAuth2DeviceAuthorizationResponse r = converter.read(OAuth2DeviceAuthorizationResponse.class, inputMessage);
} catch (HttpMessageNotReadableException ex) {
    logger.error("Device auth response unreadable", ex.getCause());
    throw new OAuth2AuthorizationException(new OAuth2Error("invalid_device_authorization_response", ex.getMessage(), null), ex);
}

Prevention

When it happens

Trigger: Calling readInternal/read on an OAuth2DeviceAuthorizationResponseHttpMessageConverter with a response body that is not valid JSON, is not a JSON object, or lacks required parameters (device_code, verification_uri) that OAuth2DeviceAuthorizationResponseParametersConverter requires.

Common situations: The device authorization endpoint returns an HTML error page instead of JSON (proxy, wrong URL), returns an error payload with HTTP 400 (e.g. authorization_pending is misused on this endpoint), or a custom message converter produces unexpected types.

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/26d91add59db8ea3. Report an issue: GitHub.