apache/dolphinscheduler · error · ServiceException

ID token is missing required claims

Error message

ID token is missing required claims

What it means

After issuer/audience/expiry pass, validateIdToken constructs an IDTokenClaimsSet from the raw claims; if that constructor throws ParseException, the token lacks required claims (per the OIDC spec: iss, sub, aud, exp, iat). The method logs "Failed to parse ID token claims, required claims may be missing." and throws ServiceException("ID token is missing required claims", e).

Solutions

  1. Decode the ID token and verify all required claims (iss, sub, aud, exp, iat) are present; fix the IdP's token/claims configuration to include them.
  2. Check whether any intermediate proxy or claims-mapping layer is stripping claims from the token.
  3. Confirm the IdP product/version actually conforms to the OIDC Core spec for the id_token claim set.
  4. If you control the token mapper (e.g. Keycloak protocol mappers), re-add the missing standard claims.

Example fix

// before: IdP token payload missing required claims
{ "iss": "https://idp", "custom_user": "alice" }

// after: conforming id_token payload
{ "iss": "https://idp", "sub": "alice", "aud": "ds-client", "exp": 1700000000, "iat": 1699999700 }
Defensive patterns

Strategy: validation

Validate before calling

// verify required OIDC claims exist before constructing IDTokenClaimsSet
List<String> required = List.of("iss", "sub", "aud", "exp", "iat");
for (String claim : required) {
    if (claimsSet.getClaim(claim) == null) {
        throw new IllegalStateException("ID token missing required claim: " + claim);
    }
}

Type guard

boolean hasRequiredClaims(JWTClaimsSet c) {
    return c.getIssuer() != null && c.getSubject() != null
        && c.getAudience() != null && c.getExpirationTime() != null
        && c.getIssueTime() != null;
}

Try / catch

try {
    return new IDTokenClaimsSet(claimsSet);
} catch (ParseException e) {
    log.error("ID token missing required claims; check IdP claim/protocol-mapper config", e);
    throw new ServiceException("ID token is missing required claims", e);
}

Prevention

When it happens

Trigger: idTokenClaims -> validateIdToken with an ID token whose claims set is structurally valid JSON but omits mandatory claims (sub, iat, exp, aud, or iss) so new IDTokenClaimsSet(claimsSet) throws ParseException.

Common situations: Non-standard or homegrown identity providers that omit required claims; IdP configured with minimal claim sets; a proxy or token-mapping middleware stripping claims; provider firmware/version that changed its default claim set.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


AI-assisted analysis of apache/dolphinscheduler@02eac45a1b (2026-09-06). Data as JSON: /api/errors/31d517286e011432. Report an issue: GitHub.

Appendix: source

Thrown at dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/security/impl/oidc/OidcAuthenticator.java:300

        if (issuer == null || !issuer.equals(providerMetadata.getIssuer().getValue())) {
            throw new ServiceException(Status.OIDC_ID_TOKEN_ISSUER_INVALID);
        }

        List<String> audiences = claimsSet.getAudience();
        if (audiences == null || !audiences.contains(providerConfig.getClientId())) {
            throw new ServiceException(Status.OIDC_ID_TOKEN_AUDIENCE_INVALID);
        }

        Date expirationTime = claimsSet.getExpirationTime();
        if (expirationTime == null || expirationTime.before(new Date())) {
            throw new ServiceException(Status.OIDC_ID_TOKEN_EXPIRED);
        }

        try {
            return new IDTokenClaimsSet(claimsSet);
        } catch (ParseException e) {
            log.error("Failed to parse ID token claims, required claims may be missing.", e);
            throw new ServiceException("ID token is missing required claims", e);
        }
    }

    /**
     * Get user info from UserInfo endpoint
     */
    private UserInfo getUserInfo(OIDCProviderMetadata providerMetadata, AccessToken accessToken) throws Exception {
        UserInfoRequest userInfoRequest = new UserInfoRequest(
                providerMetadata.getUserInfoEndpointURI(),
                accessToken);

        HTTPResponse httpResponse = userInfoRequest.toHTTPRequest().send();
        UserInfoResponse userInfoResponse = UserInfoResponse.parse(httpResponse);

        if (!userInfoResponse.indicatesSuccess()) {
            log.error("User info request failed: {}", userInfoResponse.toErrorResponse().getErrorObject());
            return null;
        }

View on GitHub (pinned to 02eac45a1b)