alibaba/nacos · critical · AccessException
Nonce mismatch: expected %s, got %s
Error message
Nonce mismatch: expected %s, got %s
What it means
Thrown by AuthorizationCodeHandler.exchangeCodeForUser when the ID token's nonce claim does not match the nonce embedded in the signed state parameter. The handler compares stateData.nonce with the token's nonce; a mismatch signals a possible token replay or session-fixation attack, so it logs an ERROR and throws AccessException with a formatted mismatch message. Note: the message uses String.format with %s placeholders at runtime.
Source
Thrown at plugin-default-impl/nacos-oidc-auth-plugin/src/main/java/com/alibaba/nacos/plugin/auth/impl/oidc/authenticate/AuthorizationCodeHandler.java:189
String tokenNonce = (String) claims.getClaim("nonce");
if (tokenNonce == null) {
String message = "Nonce not present in ID token";
if (config.isStrictNonceValidation()) {
LOGGER.error("{} - Strict validation enabled, rejecting authentication",
message);
throw new AccessException(message
+ ". Set 'nacos.plugin.auth.oidc.strict-nonce-validation=false' "
+ "if your IdP doesn't support nonce.");
} else {
LOGGER.warn("{} - Strict validation disabled, allowing authentication. "
+ "This reduces protection against replay attacks.", message);
}
} else if (!stateData.nonce.equals(tokenNonce)) {
String message = String.format("Nonce mismatch: expected %s, got %s",
stateData.nonce, tokenNonce);
LOGGER.error("{} - Possible token replay attack detected", message);
throw new AccessException(message);
}
// Map claims to user
OidcUser user = userMapper.mapToUser(claims);
user.setToken(tokens.getAccessToken().getValue());
LOGGER.info("User authenticated via authorization code: {}", user.getUsername());
return user;
} catch (AccessException e) {
throw e;
} catch (Exception e) {
LOGGER.error("Failed to exchange code for tokens", e);
throw new AccessException("Authentication failed: " + e.getMessage());
}
}
/**View on GitHub (pinned to 9b989acdf1)
Solutions
- Treat this as a security signal first — investigate whether the state parameter was tampered with in transit.
- Ensure no proxy/browser extension rewrites the state or nonce query parameters.
- Avoid concurrent OIDC logins in the same browser session that could cross-pair state and tokens.
- If the IdP is known to alter nonce, verify its nonce pass-through configuration.
Defensive patterns
Strategy: try-catch
Try / catch
try {
OidcUser user = handler.exchangeCodeForUser(code, state, redirectUri);
} catch (AccessException e) {
if (e.getMessage().contains("Nonce mismatch")) {
// security signal; investigate tampering, do not auto-retry
}
} Prevention
- Investigate nonce mismatches as potential replay/tampering attacks.
- Ensure proxies and browser extensions do not rewrite state or nonce.
- Avoid concurrent OIDC logins that can cross-pair state and tokens.
- Verify the IdP passes nonce through unmodified.
When it happens
Trigger: The nonce in the callback's state differs from the nonce in the returned ID token. This can happen if an attacker injects a different state, if the IdP mangles nonce, or if two concurrent login flows cross state and tokens.
Common situations: A real replay/replacement attack; a buggy IdP or proxy that rewrites state or nonce; concurrent browser tabs each starting an OIDC login and the wrong token is paired with the wrong state; client-side state caching bugs.
Related errors
- Invalid or expired state parameter
- Nonce not present in ID token. Set 'nacos.plugin.auth.oidc.s
- Authorization endpoint not configured
- Failed to initiate login: {errorMessage}
- Authentication failed: {errorMessage}
AI-assisted analysis of alibaba/nacos@9b989acdf1 (2026-08-14).
Data as JSON: /api/errors/c13e6ea3db407622.
Report an issue: GitHub.