{"record":{"id":"e23670d0e08fe74b","repo":"apache/dolphinscheduler","slug":"error-parsing-id-token-claims","errorCode":null,"errorMessage":"Error parsing ID token claims","messagePattern":"Error parsing ID token 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":278,"sourceCode":"            }\n\n            return ((OIDCTokenResponse) tokenResponse).getOIDCTokens();\n        } catch (java.net.URISyntaxException e) {\n            log.error(\"Invalid redirect URI configured for OIDC provider: {}\", providerId, e);\n            throw new ServiceException(\"Failed to construct OIDC redirect URI\", e);\n        }\n    }\n\n    /**\n     * Validate ID token and extract claims\n     */\n    private IDTokenClaimsSet validateIdToken(OIDCProviderMetadata providerMetadata,\n                                             OidcProviderConfig providerConfig, JWT idToken) {\n        JWTClaimsSet claimsSet;\n        try {\n            claimsSet = idToken.getJWTClaimsSet();\n        } catch (java.text.ParseException e) {\n            throw new ServiceException(\"Error parsing ID token claims\", e);\n        }\n\n        String issuer = claimsSet.getIssuer();\n        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 {","sourceCodeStart":260,"sourceCodeEnd":296,"githubUrl":"https://github.com/apache/dolphinscheduler/blob/02eac45a1b6676e639fcbfb4be2243de5771b05d/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/security/impl/oidc/OidcAuthenticator.java#L260-L296","documentation":"OidcAuthenticator.validateIdToken wraps java.text.ParseException thrown by idToken.getJWTClaimsSet() into a ServiceException with the message \"Error parsing ID token claims\". This happens when the ID token's payload is not a valid JWT claims JSON structure, so the Nimbus JWT library cannot extract the claims set. It is thrown before any issuer/audience/expiry validation takes place.","triggerScenarios":"Calling idTokenClaims -> validateIdToken with an ID token whose payload segment is malformed or not valid JSON (e.g. an opaque token, a truncated token, or a token whose payload was re-encoded incorrectly) so getJWTClaimsSet() throws java.text.ParseException.","commonSituations":"Misconfigured OIDC provider returning an opaque or non-JWT response token instead of a signed JWT; manual string manipulation of tokens in tests; proxy/gateway truncating or rewriting the token; copying a token with whitespace or missing segments.","solutions":["Log the raw ID token (never to production logs) and decode it at jwt.io to confirm it is a well-formed three-segment JWT with a JSON payload.","Verify the OIDC provider is actually issuing JWT ID tokens (response_type/id_token_issued behavior) and that you are reading the id_token field, not an access token.","Check for middleware or proxies that truncate or rewrite the token between provider and DolphinScheduler.","If the token is truncated client-side, fix the callback handling that forwards the token to the authenticator."],"exampleFix":"// before: blindly passing whatever came back from the provider\nJWT idToken = ...; // could be opaque or malformed\nvalidateIdToken(providerMetadata, providerConfig, idToken);\n\n// after: sanity-check the token shape before validating\nprivate boolean isWellFormedJwt(String token) {\n    return token != null && token.chars().filter(c -> c == '.').count() == 2;\n}\nif (!isWellFormedJwt(rawIdToken)) {\n    throw new ServiceException(\"Provider returned a malformed ID token\");\n}","handlingStrategy":"try-catch","validationCode":"private static boolean looksLikeJwt(String t) {\n    if (t == null) return false;\n    String[] parts = t.split(\"\\\\.\");\n    if (parts.length != 3) return false;\n    try { new String(java.util.Base64.getUrlDecoder().decode(parts[1]), java.nio.charset.StandardCharsets.UTF_8); return true; }\n    catch (IllegalArgumentException e) { return false; }\n}","typeGuard":"if (!(token instanceof com.nimbusds.jose.JWTParser.ParsedJWT) && !looksLikeJwt(rawToken)) { skip validation; report malformed token }","tryCatchPattern":"try {\n    claimsSet = idToken.getJWTClaimsSet();\n} catch (java.text.ParseException e) {\n    log.error(\"Malformed ID token payload\", e);\n    return redirectLogin(\"invalid_token\");\n}","preventionTips":["Never hand-edit or truncate tokens before passing them to the authenticator.","Confirm the IdP issues JWT-format id_tokens, not opaque tokens.","Decode tokens with jwt.io during integration testing to validate shape.","Check proxies/gateways do not rewrite or trim token strings."],"tags":["oidc","jwt","token-parsing","authentication"],"backgroundTag":"json-parse-error","analyzedSha":"02eac45a1b6676e639fcbfb4be2243de5771b05d","analyzedAt":"2026-09-06T17:43:00.555Z","contentChangedAt":"2026-09-06T17:43:00.555Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}