{"record":{"id":"31d517286e011432","repo":"apache/dolphinscheduler","slug":"id-token-is-missing-required-claims","errorCode":null,"errorMessage":"ID token is missing required claims","messagePattern":"ID token is missing required claims","errorType":"exception","errorClass":"ServiceException","httpStatus":null,"severity":"error","filePath":"dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/security/impl/oidc/OidcAuthenticator.java","lineNumber":300,"sourceCode":"        if (issuer == null || !issuer.equals(providerMetadata.getIssuer().getValue())) {\n            throw new ServiceException(Status.OIDC_ID_TOKEN_ISSUER_INVALID);\n        }\n\n        List<String> audiences = claimsSet.getAudience();\n        if (audiences == null || !audiences.contains(providerConfig.getClientId())) {\n            throw new ServiceException(Status.OIDC_ID_TOKEN_AUDIENCE_INVALID);\n        }\n\n        Date expirationTime = claimsSet.getExpirationTime();\n        if (expirationTime == null || expirationTime.before(new Date())) {\n            throw new ServiceException(Status.OIDC_ID_TOKEN_EXPIRED);\n        }\n\n        try {\n            return new IDTokenClaimsSet(claimsSet);\n        } catch (ParseException e) {\n            log.error(\"Failed to parse ID token claims, required claims may be missing.\", e);\n            throw new ServiceException(\"ID token is missing required claims\", e);\n        }\n    }\n\n    /**\n     * Get user info from UserInfo endpoint\n     */\n    private UserInfo getUserInfo(OIDCProviderMetadata providerMetadata, AccessToken accessToken) throws Exception {\n        UserInfoRequest userInfoRequest = new UserInfoRequest(\n                providerMetadata.getUserInfoEndpointURI(),\n                accessToken);\n\n        HTTPResponse httpResponse = userInfoRequest.toHTTPRequest().send();\n        UserInfoResponse userInfoResponse = UserInfoResponse.parse(httpResponse);\n\n        if (!userInfoResponse.indicatesSuccess()) {\n            log.error(\"User info request failed: {}\", userInfoResponse.toErrorResponse().getErrorObject());\n            return null;\n        }","sourceCodeStart":282,"sourceCodeEnd":318,"githubUrl":"https://github.com/apache/dolphinscheduler/blob/02eac45a1b6676e639fcbfb4be2243de5771b05d/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/security/impl/oidc/OidcAuthenticator.java#L282-L318","documentation":"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).","triggerScenarios":"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.","commonSituations":"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.","solutions":["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.","Check whether any intermediate proxy or claims-mapping layer is stripping claims from the token.","Confirm the IdP product/version actually conforms to the OIDC Core spec for the id_token claim set.","If you control the token mapper (e.g. Keycloak protocol mappers), re-add the missing standard claims."],"exampleFix":"// before: IdP token payload missing required claims\n{ \"iss\": \"https://idp\", \"custom_user\": \"alice\" }\n\n// after: conforming id_token payload\n{ \"iss\": \"https://idp\", \"sub\": \"alice\", \"aud\": \"ds-client\", \"exp\": 1700000000, \"iat\": 1699999700 }","handlingStrategy":"validation","validationCode":"// verify required OIDC claims exist before constructing IDTokenClaimsSet\nList<String> required = List.of(\"iss\", \"sub\", \"aud\", \"exp\", \"iat\");\nfor (String claim : required) {\n    if (claimsSet.getClaim(claim) == null) {\n        throw new IllegalStateException(\"ID token missing required claim: \" + claim);\n    }\n}","typeGuard":"boolean hasRequiredClaims(JWTClaimsSet c) {\n    return c.getIssuer() != null && c.getSubject() != null\n        && c.getAudience() != null && c.getExpirationTime() != null\n        && c.getIssueTime() != null;\n}","tryCatchPattern":"try {\n    return new IDTokenClaimsSet(claimsSet);\n} catch (ParseException e) {\n    log.error(\"ID token missing required claims; check IdP claim/protocol-mapper config\", e);\n    throw new ServiceException(\"ID token is missing required claims\", e);\n}","preventionTips":["Ensure the IdP emits all standard id_token claims (iss, sub, aud, exp, iat).","Audit any claims-mapping/protocol-mapper or proxy config that could strip claims.","Pin and test the IdP version; upgrades can change default claim sets.","Add a startup/integration test that decodes a real token and asserts claim presence."],"tags":["oidc","jwt","missing-claims","validation"],"backgroundTag":"missing-required-argument","analyzedSha":"02eac45a1b6676e639fcbfb4be2243de5771b05d","analyzedAt":"2026-09-06T17:43:00.555Z","contentChangedAt":"2026-09-06T17:43:00.555Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}