theonedev/onedev · error · AuthenticationException

ID token was expired

Error message

ID token was expired

What it means

Thrown by OpenIdConnector.processTokenResponse when the ID token's exp (expiration) claim exists and is already in the past at validation time. The connector rejects expired tokens rather than trusting an authentication that is no longer valid.

Source

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

			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)
				email = null;

			String userName = StringUtils.trimToNull(claims.getStringClaim("preferred_username"));
			String fullName = StringUtils.trimToNull(claims.getStringClaim("name"));
			List<String> groups;
			if (getGroupsClaim() != null) {
				var groupsArray = claims.getStringArrayClaim(getGroupsClaim());
				if (groupsArray != null)

View on GitHub (pinned to d44925c47c)

Solutions

  1. Synchronize the OneDev server clock with NTP, then retry the login.
  2. Retry the SSO login to obtain a fresh token promptly after redirect.
  3. Increase the ID token lifetime on the identity provider if it expires before the exchange completes.
  4. Investigate slow token endpoint responses (network latency to the provider) that delay validation past exp.
Defensive patterns

Strategy: retry

Try / catch

try {
    auth = connector.handleAuthResponse(...);
} catch (AuthenticationException e) {
    if (e.getMessage().contains("ID token was expired")) {
        // sync clocks if skewed, then retry login to get a fresh token
    }
}

Prevention

When it happens

Trigger: The token response reaches processTokenResponse after the ID token's exp time has passed — long delay between the provider issuing the token and the code-exchange/validation step, or a token with a very short expiry combined with clock skew.

Common situations: Severe OneDev server clock skew making a valid token look expired; extremely short token lifetime configured on the provider; slow networks or stalled token endpoint calls exceeding token TTL; reusing an old authorization code whose token expired.

Related errors


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