spring-projects/spring-security · error · OAuth2AuthenticationException

invalid_user_info_response

invalid_user_info_response

Error message

An error occurred while attempting to retrieve the UserInfo Resource: ${errorDetails}

What it means

DefaultOAuth2UserService.getResponse wraps any exception that occurred while calling the UserInfo endpoint (HTTP errors, OAuth2Error responses with errorDetails, I/O failures) into an OAuth2AuthenticationException with error code 'invalid_user_info_response'. The library throws it because the UserInfo Resource could not be retrieved successfully, so the authenticated user's claims are unavailable. The appended errorDetails describe the underlying cause (status code, error code, description).

Source

Thrown at oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/userinfo/DefaultOAuth2UserService.java:150

	private ResponseEntity<Map<String, Object>> getResponse(OAuth2UserRequest userRequest, RequestEntity<?> request) {
		try {
			return this.restOperations.exchange(request, PARAMETERIZED_RESPONSE_TYPE);
		}
		catch (OAuth2AuthorizationException ex) {
			OAuth2Error oauth2Error = ex.getError();
			StringBuilder errorDetails = new StringBuilder();
			errorDetails.append("Error details: [");
			errorDetails.append("UserInfo Uri: ")
				.append(userRequest.getClientRegistration().getProviderDetails().getUserInfoEndpoint().getUri());
			errorDetails.append(", Error Code: ").append(oauth2Error.getErrorCode());
			if (oauth2Error.getDescription() != null) {
				errorDetails.append(", Error Description: ").append(oauth2Error.getDescription());
			}
			errorDetails.append("]");
			oauth2Error = new OAuth2Error(INVALID_USER_INFO_RESPONSE_ERROR_CODE,
					"An error occurred while attempting to retrieve the UserInfo Resource: " + errorDetails.toString(),
					null);
			throw new OAuth2AuthenticationException(oauth2Error, oauth2Error.toString(), ex);
		}
		catch (UnknownContentTypeException ex) {
			String errorMessage = "An error occurred while attempting to retrieve the UserInfo Resource from '"
					+ userRequest.getClientRegistration().getProviderDetails().getUserInfoEndpoint().getUri()
					+ "': response contains invalid content type '" + ex.getContentType().toString() + "'. "
					+ "The UserInfo Response should return a JSON object (content type 'application/json') "
					+ "that contains a collection of name and value pairs of the claims about the authenticated End-User. "
					+ "Please ensure the UserInfo Uri in UserInfoEndpoint for Client Registration '"
					+ userRequest.getClientRegistration().getRegistrationId() + "' conforms to the UserInfo Endpoint, "
					+ "as defined in OpenID Connect 1.0: 'https://openid.net/specs/openid-connect-core-1_0.html#UserInfo'";
			OAuth2Error oauth2Error = new OAuth2Error(INVALID_USER_INFO_RESPONSE_ERROR_CODE, errorMessage, null);
			throw new OAuth2AuthenticationException(oauth2Error, oauth2Error.toString(), ex);
		}
		catch (RestClientException ex) {
			OAuth2Error oauth2Error = new OAuth2Error(INVALID_USER_INFO_RESPONSE_ERROR_CODE,
					"An error occurred while attempting to retrieve the UserInfo Resource: " + ex.getMessage(), null);
			throw new OAuth2AuthenticationException(oauth2Error, oauth2Error.toString(), ex);
		}

View on GitHub (pinned to 96852e8860)

Solutions

  1. Read the OAuth2AuthenticationException's OAuth2Error description and underlying cause (getCause) to identify the concrete failure (status, provider error code, IO error).
  2. If the cause is 401 invalid_token, force a refresh of the access token (OAuth2AuthorizedClientManager/refresh flow) and retry.
  3. Verify the configured user-info-uri is reachable and returns application/json with the user's claims (curl -H 'Authorization: Bearer <token>' <userInfoUri>).
  4. Check network/proxy/TLS settings and provider outage status; configure timeouts and retries on the RestOperations used by DefaultOAuth2UserService.

Example fix

// before
DefaultOAuth2UserService userService = new DefaultOAuth2UserService();
OAuth2User user = userService.loadUser(userRequest); // throws raw OAuth2AuthenticationException

// after
DefaultOAuth2UserService userService = new DefaultOAuth2UserService();
OAuth2User user;
try {
    user = userService.loadUser(userRequest);
}
catch (OAuth2AuthenticationException ex) {
    logger.warn("UserInfo retrieval failed: {} cause={}", ex.getError().getDescription(), ex.getCause());
    throw new AuthenticationServiceException("Upstream UserInfo failed, see logs", ex);
}
Defensive patterns

Strategy: try-catch

Validate before calling

boolean tokenPresent = authorizedClient.getAccessToken() != null
    && authorizedClient.getAccessToken().getTokenValue() != null
    && !authorizedClient.getAccessToken().getTokenValue().isBlank();

Try / catch

try {
    OAuth2User user = defaultOAuth2UserService.loadUser(userRequest);
} catch (OAuth2AuthenticationException ex) {
    if (ex.getCause() instanceof ResourceAccessException) {
        // network-level failure: retry or return 503
    } else {
        // token/provider issue: trigger re-authentication
    }
}

Prevention

When it happens

Trigger: Any exception (other than UnknownContentTypeException, which has its own catch) raised while executing the RestOperations call to the UserInfo endpoint in DefaultOAuth2UserService.getResponse — e.g. non-2xx status with an OAuth2 error body, connection failure, or read timeout during loadUser(userRequest).

Common situations: Provider returns 401/403 because the access token is expired or revoked; UserInfo endpoint is temporarily down or DNS fails; provider returns an OAuth2 error JSON (e.g. invalid_token) in the UserInfo response; corporate proxy blocks the outbound call.

Related errors


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