/ Sitecore

Sitecore Experience Forms - The anti-forgery cookie token and form field token do not match.

Issue

Sitecore experience form submission will throw an error on submit and not complete. When you investigate the log if you see the following error "The anti-forgery cookie token and form field token do not match in the error logs". The solution mentioned will help you fix the issue. ASP.NET MVC has a default security feature for forms data security. To ensure data integrity an AntiForgeryToken is generated for every user request with the forms and added as a cookie "RequestVerificationToken", also added as a hidden field on the page. When the post happens on form submit to the server, it compares the value you have in the cookie and hidden field sent with the Form. If there is a mismatch this exception occurs.

Exception Details

ERROR Application error.
Exception: System.Web.Mvc.HttpAntiForgeryException
Message: The anti-forgery cookie token and form field token do not match.
Source: System.Web.WebPages
at System.Web.Helpers.AntiXsrf.TokenValidator.ValidateTokens(HttpContextBase httpContext, IIdentity identity, AntiForgeryToken sessionToken, AntiForgeryToken fieldToken)
at System.Web.Helpers.AntiXsrf.AntiForgeryWorker.Validate(HttpContextBase httpContext)
at System.Web.Mvc.ControllerActionInvoker.InvokeAuthorizationFilters(ControllerContext controllerContext, IList1 filters, ActionDescriptor actionDescriptor) at System.Web.Mvc.Async.AsyncControllerActionInvoker.<>c__DisplayClass3_1.<BeginInvokeAction>b__0(AsyncCallback asyncCallback, Object asyncState) at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResultBase1.Begin(AsyncCallback callback, Object state, Int32 timeout)
at System.Web.Mvc.Async.AsyncControllerActionInvoker.BeginInvokeAction(ControllerContext controllerContext, String actionName, AsyncCallback callback, Object state)
at System.Web.Mvc.Controller.<>c.b__152_0(AsyncCallback asyncCallback, Object asyncState, ExecuteCoreState innerState)
at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncVoid1.CallBeginDelegate(AsyncCallback callback, Object callbackState) at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResultBase1.Begin(AsyncCallback callback, Object state, Int32 timeout)
at System.Web.Mvc.Controller.BeginExecuteCore(AsyncCallback callback, Object state)
at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResultBase1.Begin(AsyncCallback callback, Object state, Int32 timeout) at System.Web.Mvc.Controller.BeginExecute(RequestContext requestContext, AsyncCallback callback, Object state) at System.Web.Mvc.MvcHandler.<>c.<BeginProcessRequest>b__20_0(AsyncCallback asyncCallback, Object asyncState, ProcessRequestState innerState) at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncVoid1.CallBeginDelegate(AsyncCallback callback, Object callbackState)
at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResultBase`1.Begin(AsyncCallback callback, Object state, Int32 timeout)
at System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContextBase httpContext, AsyncCallback callback, Object state)
at System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
at System.Web.HttpApplication.ExecuteStepImpl(IExecutionStep step)
at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)

Analysis

In our case we had multiple servers and the load was balanced in Round Robin method. The user visits the site and starts filling a form and while he submits he might be sending the data to another server and it might think the data is invalid. Lets explore the solutions.

Solution

Method 1:

Ensure you enable sticky session or session persistence at the load balancer level. We enabled it with cookie based session persistance in F5 load balancer. In simple terms when a user opens the site he will stick to the same server till his session ends (Closing the browser or timeout). In my case we had F5 load balancer that used a custom use a cookie and ensure user ends up with the same server.

Method 2:

Generate a unique machine key and add it to the webconfig and have that added to all the front ends.
FormsSubmissionError_Machine_Key

The machine keys should be placed inside the section of the web.config file.
https://docs.microsoft.com/en-us/previous-versions/dotnet/netframework-3.0/w8h3skw9(v=vs.85)

Reference

https://stackoverflow.com/questions/18097401/the-anti-forgery-cookie-token-and-form-field-token-do-not-match-in-mvc-4

https://support.oneidentity.com/kb/206653/error-system-web-mvc-httpantiforgeryexception-0x80004005-the-anti-forgery-cookie-token-and-form-field-token-do-not-match-