I have a single-page app (user loads a bunch of HTML/JS and then makes AJAX requests without another call to MVC - only via WebAPI). In WebAPI I have the following:
public sealed class WebApiValidateAntiForgeryTokenAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(
System.Web.Http.Controllers.HttpActionContext actionContext)
{
if (actionContext == null)
{
throw new ArgumentNullException(nameof(actionContext));
}
if (actionContext.Request.Method.Method == "POST")
{
string requestUri = actionContext.Request.RequestUri.AbsoluteUri.ToLower();
if (uriExclusions.All(s => !requestUri.Contains(s, StringComparison.OrdinalIgnoreCase))) // place some exclusions here if needed
{
HttpRequestHeaders headers = actionContext.Request.Headers;
CookieState tokenCookie = headers
.GetCookies()
.Select(c => c[AntiForgeryConfig.CookieName]) // __RequestVerificationToken
.FirstOrDefault();
string tokenHeader = string.Empty;
if (headers.Contains("X-XSRF-Token"))
{
tokenHeader = headers.GetValues("X-XSRF-Token").FirstOrDefault();
}
AntiForgery.Validate(!string.IsNullOrEmpty(tokenCookie?.Value) ? tokenCookie.Value : null, tokenHeader);
}
}
base.OnActionExecuting(actionContext); // this is where it throws
}
}
Registered in Global.asax:
private static void RegisterWebApiFilters(HttpFilterCollection filters)
{
filters.Add(new WebApiValidateAntiForgeryTokenAttribute());
filters.Add(new AddCustomHeaderFilter());
}
Occasionally, I see the The anti-forgery cookie token and form field token do not match
error in my logs. When this is happening, both tokenCookie.value
and tokenHeader
are not null.
Clientside, all of my AJAX requests use the following:
beforeSend: function (request) {
request.setRequestHeader("X-XSRF-Token", $('input[name="__RequestVerificationToken"]').attr("value"););
},
With Razor generating the token once on my SPA page:
@Html.AntiForgeryToken()
I have my machine key set in Web.config.
What could be causing this?
Update I just checked logs and I'm seeing this sometimes as well:
The provided anti-forgery token was meant for user "", but the current user is "[email protected]". a few seconds ago
This occurs when a user refreshes their instance of the SPA while logged in. The SPA then drops them into the landing page instead of the inner page for some reason (User.Identity.IsAuthenticated
is true) - then they can't log in because of this error. Refreshing pulls them back inside. Not sure what this means, but I figured more info can't hurt.
Web API 2.2 - 5.2.3
? – Forgery5.2.3
– Unfathomableweb.config
hastimeout="1440" path="/" slidingExpiration="true"
set for theauthentication
entry. It's tough because I only have logs to work with; I wonder if there's anything I can do log-side to provide more insights... – UnfathomableGET
works and thenPOST
fails. – UnfathomablePOST
it's ok, the second fails, do you confirm? – ReformationMachine Key
to your webconfig and verified it ? – Ascham