prestodb/presto · error · RuntimeException
UserInfo endpoint returned error:
Error message
UserInfo endpoint returned error:
What it means
NimbusOAuth2Client.fetchUserInfoClaims got an error response from the OAuth2 UserInfo endpoint (non-success HTTP status); the endpoint's error body is appended. The claims fetch needed to establish the authenticated principal failed.
Source
Thrown at presto-main/src/main/java/com/facebook/presto/server/security/oauth2/NimbusOAuth2Client.java:576
/**
* Fetches user information claims from the UserInfo endpoint.
*
* @param accessToken the OAuth2 access token for authentication
* @return JWTClaimsSet containing user information
* @throws ParseException if the response cannot be parsed
* @throws RuntimeException if the HTTP request fails
*/
private JWTClaimsSet fetchUserInfoClaims(String accessToken) throws ParseException
{
UserInfoResponse response = httpClient.execute(
new UserInfoRequest(userinfoUrl.get(), new BearerAccessToken(accessToken)),
this::parse);
if (!response.indicatesSuccess()) {
UserInfoErrorResponse errorResponse = response.toErrorResponse();
LOG.error("Received error from UserInfo endpoint: %s", errorResponse.getErrorObject());
throw new RuntimeException("UserInfo endpoint returned error: " + errorResponse.getErrorObject());
}
return response.toSuccessResponse().getUserInfo().toJWTClaimsSet();
}
// Using this parsing method for our /userinfo response from the IdP in order to allow for different principal
// fields as defined, and in the absence of the `sub` claim. This is a "hack" solution to alter the claims
// present in the response before calling the parser provided by the oidc sdk, which fails hard if the
// `sub` claim is missing.
public UserInfoResponse parse(HTTPResponse httpResponse)
throws ParseException
{
// Check status code first and only process payload if successful
if (httpResponse.getStatusCode() != 200) {
return UserInfoErrorResponse.parse(httpResponse);
}
JSONObject body = httpResponse.getBodyAsJSONObject();View on GitHub (pinned to 55bb57d202)
Solutions
- Read the logged 'Received error from UserInfo endpoint' error object (e.g. invalid_token, insufficient_scope) to identify the cause
- Verify oauth2.access-token.audiences includes the audience the IdP puts on access tokens
- Re-authenticate to obtain a fresh access token if expired or revoked
- Confirm the proxy/load balancer forwards the Authorization: Bearer header to /userinfo
Example fix
// before // oauth2.access-token.audiences not set; IdP requires audience=coordinator // after <property name="oauth2.access-token.audiences">coordinator</property>
Defensive patterns
Strategy: try-catch
Validate before calling
// Pre-flight: curl -H "Authorization: Bearer <token>" https://idp/userinfo to confirm the token is accepted before wiring the flow
Type guard
boolean userInfoResponseOk(int status) { return status >= 200 && status < 300; } Try / catch
try { return client.getOAuth2Response(code, callbackUri, nonce); } catch (RuntimeException e) { if (e.getMessage().startsWith("UserInfo endpoint returned error")) { LOG.warn("UserInfo rejected token: {}", e.getMessage()); reauthenticate(); } throw e; } Prevention
- Configure oauth2.access-token.audiences to include the audience the IdP stamps on access tokens
- Request the scopes the userinfo endpoint requires (openid, profile, email as needed)
- Monitor the coordinator log for the 'Received error from UserInfo endpoint' entry to catch IdP-side issues early
- Verify proxies forward the Authorization header to /userinfo
When it happens
Trigger: GET /userinfo with a bearer token the IdP rejects: access token expired or revoked, wrong audience/scope, token issued for a different IdP instance, or the userinfo endpoint is down/misconfigured.
Common situations: Clock skew after authentication making the token appear expired, oauth2.access-token audiences config missing the required audience, IdP changed userinfo requirements, network/proxy stripping the Authorization header.
Related errors
- Error while fetching access token:
- /userinfo response missing principal field %s
- Unsupported 'aud' claim type in /userinfo response
- iceberg.rest.auth.oauth2 requires either a credential or a t
- Missing nonce
AI-assisted analysis of prestodb/presto@55bb57d202 (2026-09-04).
Data as JSON: /api/errors/ca1de12d3554da2a.
Report an issue: GitHub.