apache/dolphinscheduler · error · ServiceException

OIDC_ID_TOKEN_ISSUER_INVALID

OIDC_ID_TOKEN_ISSUER_INVALID

Error message

OIDC_ID_TOKEN_ISSUER_INVALID

What it means

validateIdToken compares the ID token's iss claim against the issuer published in the OIDC provider metadata and throws ServiceException(Status.OIDC_ID_TOKEN_ISSUER_INVALID) when the claim is missing or does not match exactly. Per the OIDC spec, the issuer must match the value discovered from the provider's .well-known/openid-configuration; any mismatch means the token was not issued by the configured provider.

Source

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

            throw new ServiceException("Failed to construct OIDC redirect URI", e);
        }
    }

    /**
     * Validate ID token and extract claims
     */
    private IDTokenClaimsSet validateIdToken(OIDCProviderMetadata providerMetadata,
                                             OidcProviderConfig providerConfig, JWT idToken) {
        JWTClaimsSet claimsSet;
        try {
            claimsSet = idToken.getJWTClaimsSet();
        } catch (java.text.ParseException e) {
            throw new ServiceException("Error parsing ID token claims", e);
        }

        String issuer = claimsSet.getIssuer();
        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);
        }

View on GitHub (pinned to 02eac45a1b)

Solutions

  1. Compare the configured issuer URL against the token's iss claim byte-for-byte, watching for trailing slashes, http vs https, port numbers, and path segments; fix the configured OIDC issuer URL to match exactly.
  2. Verify the provider metadata was fetched from the same environment that issued the token (staging vs production).
  3. If the provider sits behind a proxy, ensure the proxy forwards the issuer the provider itself signs with, or update the configured value accordingly.
  4. Decode the token and inspect the iss claim directly to see what value the provider is actually using.

Example fix

// before: config issuer with trailing slash doesn't match token iss
provider.issuer=https://sso.example.com/

// after: issuer must exactly equal the iss claim
provider.issuer=https://sso.example.com
Defensive patterns

Strategy: validation

Validate before calling

// before login, assert configured issuer matches provider metadata
assert config.getIssuerUrl().equals(providerMetadata.getIssuer().getValue());
// decode the incoming token and compare claims
decoded.iss == config.getIssuerUrl() // exact string equality, no trailing slash

Type guard

boolean issuerMatches(String iss, OIDCProviderMetadata md) {
    return iss != null && md.getIssuer() != null && iss.equals(md.getIssuer().getValue());
}

Try / catch

try {
    return oidcAuthenticator.idTokenClaims(providerMetadata, providerConfig, idToken);
} catch (ServiceException e) {
    log.warn("OIDC validation failed: {}", e.getMessage());
    return redirectToIdentityProvider(); // restart login
}

Prevention

When it happens

Trigger: idTokenClaims -> validateIdToken with an ID token whose iss claim is null, differs by trailing slash/scheme/port, or points to a different environment's issuer than the one configured in providerConfig/OIDCProviderMetadata.

Common situations: Configured issuer URL missing or having a trailing slash while the provider omits it (or vice versa); token issued by a staging provider while DolphinScheduler is pointed at production metadata; provider behind a reverse proxy exposing a different external issuer; http vs https mismatch.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


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