alibaba/nacos · error · AccessException
Invalid or expired state parameter
Error message
Invalid or expired state parameter
What it means
Thrown by AuthorizationCodeHandler.exchangeCodeForUser when verifyAndDecodeState(state) returns null. The state is a self-contained, HMAC-signed, base64-encoded token (nonce.expirationTime.signature). verifyAndDecodeState returns null if the state is malformed (wrong number of parts), signature verification fails, the expiration time is non-numeric, base64 decoding fails, or the state has expired (>10 minutes old). A null result triggers AccessException("Invalid or expired state parameter").
Source
Thrown at plugin-default-impl/nacos-oidc-auth-plugin/src/main/java/com/alibaba/nacos/plugin/auth/impl/oidc/authenticate/AuthorizationCodeHandler.java:160
}
}
/**
* Exchange authorization code for tokens and authenticate user.
*
* @param code authorization code from IdP
* @param state state parameter for CSRF verification
* @param redirectUri the redirect URI used in the authorization request
* @return authenticated OidcUser
* @throws AccessException if authentication fails
*/
public OidcUser exchangeCodeForUser(String code, String state, String redirectUri)
throws AccessException {
try {
// Verify and decode state (self-contained, no cache lookup needed)
StateData stateData = verifyAndDecodeState(state);
if (stateData == null) {
throw new AccessException("Invalid or expired state parameter");
}
// Exchange code for tokens
OIDCTokens tokens = exchangeCodeForTokens(code, redirectUri);
// Validate ID token
String idTokenString = tokens.getIDTokenString();
JWTClaimsSet claims = tokenValidator.validate(idTokenString);
// Verify nonce matches (protects against token replay attacks)
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(messageView on GitHub (pinned to 9b989acdf1)
Solutions
- Ensure the user completes the OIDC login within the 10-minute state validity window.
- Confirm all Nacos cluster nodes share the same OIDC client secret (used for HMAC state signing).
- Verify proxies/load balancers do not strip or rewrite the state query parameter.
- Restart the login flow to get a fresh state if the previous one expired.
Defensive patterns
Strategy: try-catch
Try / catch
try {
OidcUser user = handler.exchangeCodeForUser(code, state, redirectUri);
} catch (AccessException e) {
if ("Invalid or expired state parameter".equals(e.getMessage())) {
// prompt user to restart the login flow for a fresh state
}
} Prevention
- Complete OIDC login within the 10-minute state validity window.
- Ensure all cluster nodes share the same OIDC client secret (used for HMAC state signing).
- Verify proxies do not strip or rewrite the state parameter.
- Restart the login flow if the callback is delayed.
When it happens
Trigger: exchangeCodeForUser is called with a state that is tampered, truncated, expired (>10 min), from a different server instance with a different client secret (signature mismatch), or corrupted in transit. The CSRF/state validation fails and returns null.
Common situations: The user took more than 10 minutes between initiating login and the IdP callback; the Nacos server's client secret changed between the authorization request and the callback (multi-node with divergent config); the state was URL-mangled by a proxy; an attacker is replaying/altering the state.
Related errors
- Nonce mismatch: expected %s, got %s
- Authorization endpoint not configured
- Failed to initiate login: {errorMessage}
- Nonce not present in ID token. Set 'nacos.plugin.auth.oidc.s
- Authentication failed: {errorMessage}
AI-assisted analysis of alibaba/nacos@9b989acdf1 (2026-08-14).
Data as JSON: /api/errors/dd33f081f4154cff.
Report an issue: GitHub.