Note that there are some explanatory texts on larger screens.

plurals
  1. POProblems implementing ValidatingAntiForgeryToken attribute for Web API with MVC 4 RC
    primarykey
    data
    text
    <p>I'm making JSON-based AJAX requests and, with MVC controllers have been very grateful to Phil Haack for his <a href="http://haacked.com/archive/2011/10/10/preventing-csrf-with-ajax.aspx" rel="nofollow noreferrer">Preventing CSRF with AJAX</a> and, Johan Driessen's <a href="http://johan.driessen.se/posts/Updated-Anti-XSRF-Validation-for-ASP.NET-MVC-4-RC" rel="nofollow noreferrer">Updated Anti-XSRF for MVC 4 RC</a>. But, as I transition API-centric controllers to Web API, I'm hitting issues where the functionality between the two approaches is markedly different and I'm unable to transition the CSRF code.</p> <p>ScottS raised a similar <a href="https://stackoverflow.com/questions/11476883/web-api-and-validateantiforgerytoken">question</a> recently which was <a href="https://stackoverflow.com/a/11483099/609290">answered</a> by Darin Dimitrov. Darin's solution involves implementing an authorization filter which calls AntiForgery.Validate. Unfortunately, this code does not work for me (see next paragraph) and - honestly - is too advanced for me.</p> <p>As I understand it, Phil's solution overcomes the problem with MVC AntiForgery when making JSON requests in the absence of a form element; the form element is assumed/expected by the AntiForgery.Validate method. I <em>believe</em> that this may be why I'm having problems with Darin's solution too. I receive an HttpAntiForgeryException "The required anti-forgery form field '__RequestVerificationToken' is not present". I am certain that the token is being POSTed (albeit in the header per Phil Haack's solution). Here's a snapshot of the client's call:</p> <pre><code>$token = $('input[name=""__RequestVerificationToken""]').val(); $.ajax({ url:/api/states", type: "POST", dataType: "json", contentType: "application/json: charset=utf-8", headers: { __RequestVerificationToken: $token } }).done(function (json) { ... }); </code></pre> <p>I tried a hack by mashing together Johan's solution with Darin's and was able to get things working but am introducing HttpContext.Current, unsure whether this is appropriate/secure and why I can't use the provided HttpActionContext.</p> <p>Here's my inelegant mash-up.. the change is the 2 lines in the try block:</p> <pre><code>public Task&lt;HttpResponseMessage&gt; ExecuteAuthorizationFilterAsync(HttpActionContext actionContext, CancellationToken cancellationToken, Func&lt;Task&lt;HttpResponseMessage&gt;&gt; continuation) { try { var cookie = HttpContext.Current.Request.Cookies[AntiForgeryConfig.CookieName]; AntiForgery.Validate(cookie != null ? cookie.Value : null, HttpContext.Current.Request.Headers["__RequestVerificationToken"]); } catch { actionContext.Response = new HttpResponseMessage { StatusCode = HttpStatusCode.Forbidden, RequestMessage = actionContext.ControllerContext.Request }; return FromResult(actionContext.Response); } return continuation(); } </code></pre> <p>My questions are:</p> <ul> <li>Am I correct in thinking that Darin's solution assumes the existence of a form element?</li> <li>What's an elegant way to mash-up Darin's Web API filter with Johan's MVC 4 RC code?</li> </ul> <p>Thanks in advance!</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload