prestodb/presto · error · ParseException
Unsupported 'aud' claim type in /userinfo response
Error message
Unsupported 'aud' claim type in /userinfo response
What it means
The /userinfo parser validates the 'aud' claim: it must be a string or array of strings, and the audience must include the OAuth2 client id or one of the configured access-token audiences. A claim of an unexpected JSON type throws ParseException('Unsupported 'aud' claim type in /userinfo response').
Source
Thrown at presto-main/src/main/java/com/facebook/presto/server/security/oauth2/NimbusOAuth2Client.java:621
httpResponse.setBody(body.toJSONString());
}
Object audClaim = body.get("aud");
// only validate aud claim if it exists
if (audClaim != null) {
List<String> audiences;
if (audClaim instanceof String) {
audiences = List.of((String) audClaim);
}
else if (audClaim instanceof List<?>) {
audiences = ((List<?>) audClaim).stream()
.filter(String.class::isInstance)
.map(String.class::cast)
.collect(toImmutableList());
}
else {
throw new ParseException("Unsupported 'aud' claim type in /userinfo response");
}
if (!audiences.contains(clientId.getValue()) && Collections.disjoint(audiences, accessTokenAudiences)) {
throw new ParseException("Invalid audience in /userinfo response");
}
}
return UserInfoSuccessResponse.parse(httpResponse);
}
private Optional<JWTClaimsSet> parseAccessToken(String accessToken)
{
try {
return Optional.of(accessTokenProcessor.process(accessToken, null));
}
catch (java.text.ParseException | BadJOSEException | JOSEException e) {
LOG.debug(e, "Failed to parse JWT access token");
return Optional.empty();View on GitHub (pinned to 55bb57d202)
Solutions
- Inspect the raw /userinfo response and confirm the aud claim type
- Fix or upgrade the IdP so aud is a string or array of strings
- If the IdP cannot be changed, configure audiences correctly or use an IdP that emits standard OIDC claims
- Check for a proxy rewriting the userinfo JSON body
Example fix
// before
{"aud": {"client": "abc"}} // object, unsupported
// after
{"aud": ["abc"]} // array of strings, supported Defensive patterns
Strategy: type-guard
Validate before calling
// Pre-check the aud claim type before parsing
Object aud = userInfoJson.opt("aud");
if (aud != null && !(aud instanceof String) && !(aud instanceof org.json.JSONArray)) { throw new IllegalStateException("Unsupported aud type in /userinfo response"); } Type guard
boolean isSupportedAudClaim(Object aud) { if (aud instanceof String) return true; if (aud instanceof org.json.JSONArray) { for (int i = 0; i < ((org.json.JSONArray) aud).length(); i++) { if (!(((org.json.JSONArray) aud).opt(i) instanceof String)) return false; } return true; } return false; } Try / catch
try { return parseUserInfoResponse(httpResponse); } catch (com.nimbusds.oauth2.sdk.ParseException e) { if (e.getMessage().contains("aud")) { LOG.error("IdP emitted non-standard aud claim: {}", httpResponse.getBodyAsJSONObject().opt("aud")); } throw e; } Prevention
- Verify the IdP emits aud as a string or array of strings during setup
- Confirm oauth2.client-id and oauth2.access-token.audiences cover all audiences the IdP uses
- Watch for IdP/gateway upgrades that alter userinfo JSON serialization
- Log the raw aud value on parse failure to diagnose quickly
When it happens
Trigger: The IdP returns 'aud' as a nested array of non-strings, an object, a number, or another non-string/non-list JSON type in the /userinfo response.
Common situations: Non-standard or custom IdPs emitting unusual aud representations, IdP version changes altering claim serialization, misbehaving API gateways rewriting the userinfo body.
Related errors
- /userinfo response missing principal field %s
- UserInfo endpoint returned error:
- NOT_SUPPORTED
- 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/0fec40c31a0ecfee.
Report an issue: GitHub.