{"record":{"id":"1ec5963c4ab42c55","repo":"apache/dolphinscheduler","slug":"oidc-id-token-audience-invalid","errorCode":"OIDC_ID_TOKEN_AUDIENCE_INVALID","errorMessage":"OIDC_ID_TOKEN_AUDIENCE_INVALID","messagePattern":"OIDC_ID_TOKEN_AUDIENCE_INVALID","errorType":"error_code","errorClass":"ServiceException","httpStatus":null,"severity":"error","filePath":"dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/security/impl/oidc/OidcAuthenticator.java","lineNumber":288,"sourceCode":"     * 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 {\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     */","sourceCodeStart":270,"sourceCodeEnd":306,"githubUrl":"https://github.com/apache/dolphinscheduler/blob/02eac45a1b6676e639fcbfb4be2243de5771b05d/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/security/impl/oidc/OidcAuthenticator.java#L270-L306","documentation":"validateIdToken checks that the ID token's aud claim contains the configured client_id and throws ServiceException(Status.OIDC_ID_TOKEN_AUDIENCE_INVALID) when the audience list is null or does not include providerConfig.getClientId(). The audience check ensures the token was minted for this specific client, not for another relying party.","triggerScenarios":"idTokenClaims -> validateIdToken with an ID token whose aud claim omits the configured clientId, e.g. the client_id in DolphinScheduler's OIDC config differs from the one registered at the provider, or the token was issued to a different client entirely.","commonSituations":"client_id changed in DolphinScheduler config but the provider still issues tokens for the old client; multiple client registrations across environments; single-page apps receiving tokens with azp/multiple audiences where the expected client is only in azp; copy-pasting credentials from another application.","solutions":["Verify the clientId in the DolphinScheduler OIDC provider config exactly matches the client_id registered at the OIDC provider and the one used in the authorization request.","Decode the ID token and inspect the aud (and azp) claims to see which audience the provider is actually granting.","Re-do the authorization-code exchange so the token is requested with the current client_id rather than reusing an old token.","If the provider issues multi-audience tokens, ensure your client_id is listed in aud or configure the provider to include it."],"exampleFix":"// before: client id mismatch\nprovider.clientId=dolphinscheduler-old\n\n// after: client id matching the registration at the IdP\nprovider.clientId=dolphinscheduler-prod","handlingStrategy":"validation","validationCode":"// decode token and verify audience before validating\nSet<String> aud = new HashSet<>(decoded.getAudience());\nif (!aud.contains(config.getClientId())) {\n    throw new IllegalStateException(\"Token audience does not include configured clientId\");\n}","typeGuard":"boolean audienceOk(JWTClaimsSet c, String clientId) {\n    try { return c.getAudience() != null && c.getAudience().contains(clientId); }\n    catch (java.text.ParseException e) { return false; }\n}","tryCatchPattern":"try {\n    return idTokenClaims(providerMetadata, providerConfig, idToken);\n} catch (ServiceException e) {\n    if (String.valueOf(e.getMessage()).contains(\"AUDIENCE_INVALID\")) {\n        log.error(\"Check clientId configuration: {} vs token aud claim\", providerConfig.getClientId());\n    }\n    throw e;\n}","preventionTips":["Keep clientId in DolphinScheduler config identical to the IdP client registration.","After rotating credentials at the IdP, update DolphinScheduler immediately.","Inspect aud/azp claims during IdP integration testing.","Configure the IdP to include your client_id in aud for multi-audience setups."],"tags":["oidc","jwt","audience-validation","configuration"],"backgroundTag":"invalid-config-value","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"}