theonedev/onedev · error · AuthenticationException
Invalid issue date of ID token
Error message
Invalid issue date of ID token
What it means
Thrown by OpenIdConnector.processTokenResponse when the ID token's iat (issue time) claim is in the future by more than a 10-second tolerance (now.plusSeconds(10)). The connector rejects tokens apparently issued in the future, which indicates clock skew or a forged/manipulated token.
Source
Thrown at server-plugin/server-plugin-sso-openid/src/main/java/io/onedev/server/plugin/sso/openid/OpenIdConnector.java:225
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)
email = null;
String userName = StringUtils.trimToNull(claims.getStringClaim("preferred_username"));
String fullName = StringUtils.trimToNull(claims.getStringClaim("name"));
List<String> groups;View on GitHub (pinned to d44925c47c)
Solutions
- Synchronize clocks with NTP on the OneDev server (e.g. systemd-timesyncd/chrony) and on the identity provider host.
- Restart the SSO login to get a freshly issued token after fixing clock skew.
- Check container/VM time settings (host clock passthrough, no paused/snapshotted clocks).
- If skew is small and unavoidable, note the 10-second tolerance and reduce skew below it.
Example fix
# before: clock skewed # after sudo chronyc makestep # or configure NTP on the OneDev host
Defensive patterns
Strategy: retry
Validate before calling
long skewMinutes = Math.abs(DateTime.now().getMillis() - System.currentTimeMillis()); // verify host clock via NTP before SSO rollout: chronyc tracking / ntpq -p
Try / catch
try {
auth = connector.handleAuthResponse(...);
} catch (AuthenticationException e) {
if (e.getMessage().contains("Invalid issue date")) {
// resync clocks (NTP) and retry login
}
} Prevention
- Run NTP/chrony on the OneDev server and the identity provider.
- Watch for VM snapshot/resume clock drift.
- Keep container clocks synced with the host.
- Alert on clock skew between SSO components.
When it happens
Trigger: claims.getIssueTime() is after server time plus 10 seconds when the token response is processed — the identity provider's clock is ahead of the OneDev server clock, or a misbehaving proxy returned a cached/pre-issued token with a future iat.
Common situations: NTP not running or drifting on either the OneDev server or the identity provider host; containers with wrong timezone/clock settings; VM resumed from snapshot with skewed clock.
Related errors
- Inconsistent issuer in provider metadata and ID token
- ID token was expired
- OIDC error: Inconsistent sub in ID token and userinfo
- Unsolicited OIDC authentication response
- Unsolicited OIDC authentication response
AI-assisted analysis of theonedev/onedev@d44925c47c (2026-09-06).
Data as JSON: /api/errors/bd784b278bfc8ff2.
Report an issue: GitHub.