{"record":{"id":"c13e6ea3db407622","repo":"alibaba/nacos","slug":"nonce-mismatch-expected-s-got-s","errorCode":null,"errorMessage":"Nonce mismatch: expected %s, got %s","messagePattern":"Nonce mismatch: expected (.+?), got (.+?)","errorType":"exception","errorClass":"AccessException","httpStatus":401,"severity":"critical","filePath":"plugin-default-impl/nacos-oidc-auth-plugin/src/main/java/com/alibaba/nacos/plugin/auth/impl/oidc/authenticate/AuthorizationCodeHandler.java","lineNumber":189,"sourceCode":"            String tokenNonce = (String) claims.getClaim(\"nonce\");\n            \n            if (tokenNonce == null) {\n                String message = \"Nonce not present in ID token\";\n                if (config.isStrictNonceValidation()) {\n                    LOGGER.error(\"{} - Strict validation enabled, rejecting authentication\",\n                        message);\n                    throw new AccessException(message\n                        + \". Set 'nacos.plugin.auth.oidc.strict-nonce-validation=false' \"\n                        + \"if your IdP doesn't support nonce.\");\n                } else {\n                    LOGGER.warn(\"{} - Strict validation disabled, allowing authentication. \"\n                        + \"This reduces protection against replay attacks.\", message);\n                }\n            } else if (!stateData.nonce.equals(tokenNonce)) {\n                String message = String.format(\"Nonce mismatch: expected %s, got %s\",\n                    stateData.nonce, tokenNonce);\n                LOGGER.error(\"{} - Possible token replay attack detected\", message);\n                throw new AccessException(message);\n            }\n            \n            // Map claims to user\n            OidcUser user = userMapper.mapToUser(claims);\n            user.setToken(tokens.getAccessToken().getValue());\n            \n            LOGGER.info(\"User authenticated via authorization code: {}\", user.getUsername());\n            return user;\n            \n        } catch (AccessException e) {\n            throw e;\n        } catch (Exception e) {\n            LOGGER.error(\"Failed to exchange code for tokens\", e);\n            throw new AccessException(\"Authentication failed: \" + e.getMessage());\n        }\n    }\n    \n    /**","sourceCodeStart":171,"sourceCodeEnd":207,"githubUrl":"https://github.com/alibaba/nacos/blob/9b989acdf181d00898f2e8839257bb2b2a3cefe3/plugin-default-impl/nacos-oidc-auth-plugin/src/main/java/com/alibaba/nacos/plugin/auth/impl/oidc/authenticate/AuthorizationCodeHandler.java#L171-L207","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n    OidcUser user = handler.exchangeCodeForUser(code, state, redirectUri);\n} catch (AccessException e) {\n    if (e.getMessage().contains(\"Nonce mismatch\")) {\n        // security signal; investigate tampering, do not auto-retry\n    }\n}","preventionTips":["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."],"tags":["auth","oidc","nonce","replay-attack","security","csrf","access-denied","java"],"backgroundTag":null,"analyzedSha":"9b989acdf181d00898f2e8839257bb2b2a3cefe3","analyzedAt":"2026-08-14T07:17:31.569Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}