theonedev/onedev · error · AuthenticationException

Inconsistent issuer in provider metadata and ID token

Error message

Inconsistent issuer in provider metadata and ID token

What it means

Thrown by OpenIdConnector.processTokenResponse when the 'iss' (issuer) claim of the received ID token does not equal the issuer advertised in the provider's discovery metadata (getCachedProviderMetadata().getIssuer()). This per OIDC spec validation prevents token substitution or misconfigured provider endpoints from yielding tokens minted by a different issuer.

Source

Thrown at server-plugin/server-plugin-sso-openid/src/main/java/io/onedev/server/plugin/sso/openid/OpenIdConnector.java:220

			return (Boolean)jsonValue;
		} else if (jsonValue instanceof JSONArray) {
			JSONArray jsonArray = (JSONArray) jsonValue;
			if (!jsonArray.isEmpty())
				return (Boolean) jsonArray.iterator().next();
			else
				return null;
		} else {
			return null;
		}
	}
	
	protected SsoAuthenticated processTokenResponse(OIDCTokenResponse tokenResponse) {
		try {
			JWT idToken = tokenResponse.getOIDCTokens().getIDToken();
			JWTClaimsSet claims = idToken.getJWTClaimsSet();
			
			if (!claims.getIssuer().equals(getCachedProviderMetadata().getIssuer()))
				throw new AuthenticationException(_T("Inconsistent issuer in provider metadata and ID token"));
			
			DateTime now = new DateTime();
			
			if (claims.getIssueTime() != null && claims.getIssueTime().after(now.plusSeconds(10).toDate()))
				throw new AuthenticationException(_T("Invalid issue date of ID token"));
			
			if (claims.getExpirationTime() != null && now.toDate().after(claims.getExpirationTime()))
				throw new AuthenticationException(_T("ID token was expired"));

			Session.get().setAttribute(SESSION_ATTR_ID_TOKEN, idToken.serialize());

			String subject = claims.getSubject();
			String email = StringUtils.trimToNull(claims.getStringClaim("email"));

			Boolean emailVerified = claims.getBooleanClaim("email_verified");
			if (emailVerified == null)
				emailVerified = claims.getBooleanClaim("emailVerified");
			if (emailVerified != null && !emailVerified)

View on GitHub (pinned to d44925c47c)

Solutions

  1. Make the connector's provider metadata (well-known/discovery) URL exactly match the issuer URL in the token (scheme, host, port, path).
  2. Fix reverse-proxy configuration so the provider emits its public (external) URL as issuer and OneDev uses that same URL.
  3. Avoid mixing http/https or localhost vs FQDN between discovery URL and the provider's real issuer.
  4. Update the provider (e.g. Keycloak realm URL) config in the OneDev SSO connector after any provider URL change.

Example fix

// before: discovery via internal host
wellKnownConfiguration: "http://keycloak.internal:8080/realms/myrealm/.well-known/openid-configuration"
// after: use the same public issuer the token carries
wellKnownConfiguration: "https://sso.example.com/realms/myrealm/.well-known/openid-configuration"
Defensive patterns

Strategy: validation

Validate before calling

// Before configuring, fetch discovery metadata and compare with expected issuer:
var meta = HttpResource.retrieve(wellKnownUrl);
System.out.println(meta.toJSONObject().get("issuer")); // must match token 'iss' exactly

Try / catch

try {
    auth = connector.handleAuthResponse(...);
} catch (AuthenticationException e) {
    if (e.getMessage().contains("Inconsistent issuer")) {
        // fix provider metadata URL to match the token issuer, then retry
    }
}

Prevention

When it happens

Trigger: After exchanging the authorization code, the ID token's iss claim differs from the well-known configuration issuer — e.g. connector points at a discovery URL whose metadata issuer uses a different scheme/host/path than the token endpoint actually issuing tokens.

Common situations: Provider behind a proxy reached via different hostnames (internal vs external URL); http vs https mismatch in the well-known URL; issuer with/without trailing path (realm name) misconfigured; switching from HTTP to HTTPS on the identity provider without updating connector settings; older provider versions omitting the issuer check nuances.

Related errors


AI-assisted analysis of theonedev/onedev@d44925c47c (2026-09-06). Data as JSON: /api/errors/f9930dae3e79325e. Report an issue: GitHub.