{"record":{"id":"4d0575230b6e8a05","repo":"dotnet/aspnetcore","slug":"the-antiforgery-cookie-token-and-request-token-do","errorCode":null,"errorMessage":"The antiforgery cookie token and request token do not match.","messagePattern":"The antiforgery cookie token and request token do not match\\.","errorType":"exception","errorClass":"AntiforgeryValidationException","httpStatus":null,"severity":"error","filePath":"src/Antiforgery/src/Internal/DefaultAntiforgery.cs","lineNumber":200,"sourceCode":"\n        // Extract cookie & request tokens\n        AntiforgeryToken deserializedCookieToken;\n        AntiforgeryToken deserializedRequestToken;\n\n        DeserializeTokens(\n            httpContext,\n            antiforgeryTokenSet,\n            out deserializedCookieToken,\n            out deserializedRequestToken);\n\n        // Validate\n        if (!_tokenGenerator.TryValidateTokenSet(\n            httpContext,\n            deserializedCookieToken,\n            deserializedRequestToken,\n            out var message))\n        {\n            throw new AntiforgeryValidationException(message);\n        }\n    }\n\n    /// <inheritdoc />\n    public void SetCookieTokenAndHeader(HttpContext httpContext)\n    {\n        ArgumentNullException.ThrowIfNull(httpContext);\n\n        CheckSSLConfig(httpContext);\n\n        var antiforgeryFeature = GetCookieTokens(httpContext);\n        if (!antiforgeryFeature.HaveStoredNewCookieToken && antiforgeryFeature.NewCookieToken != null)\n        {\n            if (antiforgeryFeature.NewCookieTokenString == null)\n            {\n                antiforgeryFeature.NewCookieTokenString =\n                    _tokenSerializer.Serialize(antiforgeryFeature.NewCookieToken);\n            }","sourceCodeStart":182,"sourceCodeEnd":218,"githubUrl":"https://github.com/dotnet/aspnetcore/blob/294cab2f9b2e03af6b953820c7ab497c3c8b7ad9/src/Antiforgery/src/Internal/DefaultAntiforgery.cs#L182-L218","documentation":"Thrown during TryValidateTokenSet when the SecurityToken embedded in the deserialized cookie token does not equal the SecurityToken embedded in the deserialized request token. The antiforgery system binds the two tokens together with a shared random SecurityToken so that a request token from one session cannot validate against a cookie from another; a mismatch means they are not a matched pair. Results in AntiforgeryValidationException.","triggerScenarios":"Detected at DefaultAntiforgeryTokenGenerator.cs:136 when !object.Equals(cookieToken.SecurityToken, requestToken.SecurityToken). Commonly happens when the request token was generated against a different cookie token than the one currently present (e.g., the cookie was refreshed/rotated but the client still sends an old request token).","commonSituations":"The antiforgery cookie expired and was regenerated by GetAndStoreTokens, but the client still submits a stale request token cached in the page; the user opened a form in one tab, the cookie rotated in another tab, and the old form is submitted; load-balanced environments with inconsistent data-protection keys causing tokens generated on one node to not match.","solutions":["Regenerate tokens on the client side: have the page fetch fresh tokens via GetAndStoreTokens before submitting, or reload the page so the new request token matches the new cookie.","Ensure data protection keys are shared across all application instances (persist keys to Redis/SQL/Azure Blob) so tokens generated on one node validate on another.","Check that the cookie isn't being dropped or rewritten by a reverse proxy or CDN; confirm the same cookie name (default .AspNetCore.Antiforgery) is used everywhere.","Verify the application didn't change Cookie.Name or data-protection purpose strings between requests."],"exampleFix":"// before — request token cached in static HTML, goes stale after cookie rotation\n<input name=\"__RequestVerificationToken\" value=\"@tokenSet.RequestToken\" />\n\n// after — refresh tokens on submit if they may be stale\nasync function getFreshToken() {\n  const res = await fetch('/antiforgery/token');\n  return (await res.json()).requestToken;\n}","handlingStrategy":"try-catch","validationCode":"// Client-side: refresh tokens before submitting long-lived pages\ndocument.querySelector('form').addEventListener('submit', async (e) => {\n  // optionally re-fetch tokens if the page is old\n});","typeGuard":null,"tryCatchPattern":"try\n{\n    await _antiforgery.ValidateRequestAsync(HttpContext);\n}\ncatch (AntiforgeryValidationException ex)\n{\n    _logger.LogWarning(\"Token mismatch, likely stale pair: {Msg}\", ex.Message);\n    return BadRequest(\"Your session token has expired. Please reload and retry.\");\n}","preventionTips":["Share data-protection keys across all instances to prevent cross-node token invalidation.","Set no-cache headers on pages containing tokens so the browser always fetches fresh tokens.","Regenerate tokens via GetAndStoreTokens on page load."],"tags":["antiforgery","security","csrf","token-validation","data-protection"],"analyzedSha":"294cab2f9b2e03af6b953820c7ab497c3c8b7ad9","analyzedAt":"2026-08-06T20:08:02.189Z","schemaVersion":2},"datasetVersion":"2026-08-06T23:17:07.152Z"}