anti forgery token using rest client - asp.net-mvc

I have a mvc site and I use the ValidateAntiForgeryToken on some of my action methods. On view I have the following line of code:
#Html.AntiForgeryToken()
The problem starts when I tried to call the function using postman rest client.
I get an error:
The required anti-forgery form field "__RequestVerificationToken" is
not present.
I tried sending the cookies needed as such:
Cookie: ASP.NET_SessionId=hgpv04mkuldbex45im3gco; __RequestVerificationToken=2Of_03RzDacR4Hf-sWS3f_G0kZs1
But still getting the same error.
Anyone knows what the hell am I missing please?

It is two part
Part 1 is to add to the cshtml
#Html.AntiForgeryToken()
Part 2 is to add this to the method
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult CreateSomething(Something model)
{
if (ModelState.IsValid)
{
//your logic
}
return View(ModelName);
}

Related

ValidateAntiForgeryToken doesn't do the only thing it is suppose to do

I am implementing AntiForgeryToken feature to my asp.net core mvc project. As usual, I have included #Html.AntiForgeryToken() inside the form tags so it looks like this:
<form method="post" action="mycontroller/myaction">
#Html.AntiForgeryToken()
<input type="text" name="myInput"/>
<button type="submit">Submit</button>
</form>
and as you can imagine, here is the myaction action in my mycontroller controller:
[HttpPost]
[Route("somepath")]
[ValidateAntiForgeryToken]
public IActionResult myaction()
{
//some code here
}
Now the problem is, I NEVER GET ANY ERROR!!
I removed the #Html.AntiForgeryToken from the view and the [ValidateAntiForgeryToken] doesn't do a thing! the post action works just fine.
Here are two things I have tried that might give you a clue:
I tried both [ValidateAntiForgeryToken] and [ValidateAntiForgeryToken()], no difference!
Someone said that the attribute only works in authorized controllers or actions. Tried this in my controller that has the [Authorize] tag.
PS: I have not added any code in my Startup.cs like services.AddMvc(...). Could it be something about that??
Please help.
ValidateAntiForgeryToken is used to prevent cross-site request forgery attacks.
Antiforgery middleware has been added to the Dependency injection container when services.AddMvc() is called,and The FormTagHelper has injected antiforgery tokens into HTML form elements already.You don't need to call #Html.AntiForgeryToken()
For more details ,you could check this document.
In and MVC app (which you have there), request verification using an anti forgery token is opt in. You opt in by decorating the controller action with the [ValidateAntiForgeryToken] attribute. If you omit the attribute, the request is not subject to verification. In each of the scenarios you described, there is no reason for an error. The only time you are likely to see an error (in the shape of a 400 HTTP status code) in an MVC app is if you decorate the action with the [ValidateAntiForgeryToken] attribute but the cookie or token are not included as part of the request payload.
In Razor Pages, all POST requests are verified by default. You can opt out of request verification, in which case you can opt in on a page by page basis by adding the attribute to the PageModel class (not the handler method) The anti-forgery token is generated by the form tag helper when the method is set to POST in both Razor Pages and MVC views.
Sometimes, you might want to post without a form (using AJAX most commonly) in which case you need to generate the anti-forgery token in the view so that you can include it within the post request payload. The Html.AntiforgeryToken helper (which is a legacy from older versions of MVC) provides a convenient way to do that.
I've written in detail about this process here: https://www.learnrazorpages.com/security/request-verification

MVC.NET how to secure submitting forms after edit

When I want to submit a form to save an edited record, I should pass its Id to controller. Then a client (or attacker) may change some information (e.g. this Id) on the form that I don't want to be changed. I can create a hashed hidden field to check that read-only fields have not been changed and verify it when it is posted to controller.
Is there any other good practice for this issue?
Thanks
You can encode data you want to protect with server side algorithm, that way that view receives encoded data only. When user passed the form to controller you decode data and check for validity. Also remember to implement not only client side validation, but also server side validation for your model.
AntiForgeryToken: A great feature in ASP.NET MVC is the AntiForgeryToken. This Generates a hidden form field (anti-forgery token) that is validated when the form is submitted. The anti-forgery token can be used to help protect your application against cross-site request forgery
.cshtml Code
#using (Html.BeginForm("Index", "Home"))
{
#Html.AntiForgeryToken()
}
Controller Code
[ValidateAntiForgeryToken()]
[HttpPost]
public ActionResult Index()
{
//Your Code
return View();
}

The required anti-forgery cookie "__RequestVerificationToken" is not present.

The required anti-forgery cookie "__RequestVerificationToken" is not present.
I have added in cshtml and in Controller also
using (Html.BeginForm())
{
#Html.AntiForgeryToken()
//some code
}
[HttpGet]
[ValidateAntiForgeryToken]
public ActionResult Index()
{
using (var db = new SampleEntities())
{
return View(db.Rfps.ToList());
}
}
In my case, I had this in my web.config:
<httpCookies requireSSL="true" />
But my project was set to not use SSL. Commenting out that line or setting up the project to always use SSL solved it.
The issue is because you are using a ValidateAntiForgeryToken attribute on a GET request.
You don't need to use this attribute for GET actions. Look here for more information:
In my case, it was because I ran another Asp.Net website before. So the cookies could not match for localhost.
I cleared my cookies (just for localhost) and everything is fine now.

MVC 4 Anti-Forgery Error with Login

I have an MVC 4 web application with ELMAH running in the background to help me keep track of any errors occurring on the website. I have noticed a good few errors happening stating the following
System.Web.Mvc.HttpAntiForgeryException: The required anti-forgery
form field "__RequestVerificationToken" is not present.
The majority of these errors seem to be happening when a user attempts to log into my website. To be honest, I just used the out of the box MVC 4 Visual Studio login View for this, ie, my View has the following
#using (Html.BeginForm(new { ReturnUrl = ViewBag.ReturnUrl }))
{
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
//textboxes for username and password
//login button
}
And then my Account Controller with Login Action
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public ActionResult Login(LoginModel model, string returnUrl)
{
if (ModelState.IsValid && _accountService.Logon(model.Email, model.Password,false))
{
}
}
Do you think anything looks wrong with this code? I am not sure how to get rid of these errors.
Any feedback or advice would be appreciated.
Thanks.
I've had a user report the same problem and we've identified that it happens when they click the login button twice.
I assume the problem is that logging in changes the token, but when the form is resubmitted it has the old token. One solution would be to disable to login button so the user can only submit the form once.
That's not perfect though, as the login may time out or something and they won't be able to try again without reloading the page, so I'm currently looking for better solutions.

Uploadify problem with Authentication Token and Html.AntiforgeryToken (plugin does not send cookies)

Some time ago I had a problem with Uploadify plugin for which I did found a solution described in this answer.
The problem in that question was substantially due to the fact that Uploadify uses a flash plugin and the flash plugin does not share the authentication cookie with the server-side code.
The solution was to use a custom version of the Authorize attribute (the code was published within that answer).
The attribute [TokenizedAuthorize] was placed on the controller class as follow
[TokenizedAuthorize]
[CheckForActiveService]
public partial class DocumentController : BaseController
{
}
Some days ago I have added the <%: Html.AntiForgeryToken() %> inside the form and the
[ValidateAntiForgeryToken] to the action method as in the following sample:
[HttpPost]
[ValidateAntiForgeryToken]
public virtual ActionResult Upload( HttpPostedFileBase fileData ) {
}
Anyway I am not anymore able to upload files to the server. Using the debugger I have been able to check that after the last line in the TokenizedAuthorize code
return base.AuthorizeCore( httpContext );
I get an exception handled by Elmah that says
System.Web.Mvc.HttpAntiForgeryException: invalid or not specified anti forgery token
in System.Web.Mvc.ValidateAntiForgeryTokenAttribute.OnAuthorization(AuthorizationContext filterContext)
in System.Web.Mvc.ControllerActionInvoker.InvokeAuthorizationFilters(ControllerContext controllerContext, IList`1 filters, ActionDescriptor actionDescriptor)
in System.Web.Mvc.ControllerActionInvoker.InvokeAction(ControllerContext controllerContext, String actionName)
This exception seems to confirm that the [ValidateAntiForgeryToken] attribute is being called... but I cant understand where is the issue with my code.
Any help?
EDIT:
Using the debugger I have checked the value of the __RequestVerificationToken form parameter and, as you can see, it is correctly populated with the value from <%: Html.AntiForgeryToken() %>
EDIT 2:
I can also confirm that if I comment the [ValidateAntiForgeryToken] on the Post Action
everything works as expected
EDIT 3:
As the post function is an ajax call done by the uploadify plugin the AntiForgeryToken is added to the post parameters using a small js function as in the following code
$('#fileInput').uploadify({
//other uploadify parameters removed for brevity
scriptData: AddAntiForgeryToken({ AuthenticationToken: auth }),
});
where AddAntiForgeryToken() is a javascript function defined in my master page to support all the ajax post to the server
<%-- used for ajax in AddAntiForgeryToken() --%>
<form id="__AjaxAntiForgeryForm" action="#" method="post">
<%: Html.AntiForgeryToken() %>
</form>
// Encapsulate the Anti Forgery Token fetching
AddAntiForgeryToken = function (data) {
data.__RequestVerificationToken = $('#__AjaxAntiForgeryForm input[name=__RequestVerificationToken]').val();
return data;
};
EDIT 4:
Darin intuition is correct. The Uploadify script is not sending any cookie to the server and so the server cannot validate the AntiForgeryToken. How can I add the cookie inside the Uploadify scriptData section?
You must ensure that a cookie with the same value as the __RequestVerificationToken field is sent in the request. Normally this cookie is emitted by the Html.AntiforgeryToken() and it must be done on the server because its value is encrypted with the server machine keys. If the request is performed by a Flash client I don't know whether it sends cookies. If this is not the case you will need to manually send it.
There's also something else that you should be aware of and which would throw the same exception although I don't think that it is applicable in your case but worth checking. When you use the Html.AntiforgeryToken() helper if there's a logged in user his username is part if the emitted cookie. If you then try to POST to a controller action decorated with the [ValidateAntiForgeryToken] it will verify that the currently logged in user is the same as the one when the cookie was emitted and if it isn't it will throw this exception. So what I have seen is people using the Html.AntiforgeryToken() to generate some html forms as an anonymous user and then using AJAX to log-in a user and once logged in the user submits the form - it will fail.

Resources