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
- Read the OAuth2AuthenticationException's OAuth2Error description and underlying cause (getCause) to identify the concrete failure (status, provider error code, IO error).
- If the cause is 401 invalid_token, force a refresh of the access token (OAuth2AuthorizedClientManager/refresh flow) and retry.
- Verify the configured user-info-uri is reachable and returns application/json with the user's claims (curl -H 'Authorization: Bearer <token>' <userInfoUri>).
- 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
- Refresh expired access tokens before calling loadUser
- Set sane connect/read timeouts on the RestOperations used for UserInfo
- Monitor provider health and log ex.getError().getDescription() with the cause
- Use issuer-uri discovery so the correct userinfo endpoint is used
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
- missing_user_info_uri
- missing_user_name_attribute
- invalid_user_info_response
- invalid_scope
- oidc_provider_not_configured
AI-assisted analysis of spring-projects/spring-security@96852e8860 (2026-09-10).
Data as JSON: /api/errors/3920abb79d9f4a25.
Report an issue: GitHub.