Reputation: 35843
Context
I've noticed that after creating a new ASP.NET Core Razor page application in VS 2019 from its out of the box template, even the purest html form with the purest model class renders output with <input name="__RequestVerificationToken" type="hidden" value="...">
Question
Am I missing something and there is somewhere an explicit attribute/statement which instructs ASP.NET Core to add anti forgery or now this is the default? (which makes using [AutoValidateAntiforgeryToken]
obsolete)
...or...
It is just the <input name="__RequestVerificationToken" type="hidden" value="...">
which is rendered always unconditionally and with the [AutoValidateAntiforgeryToken]
I can turn on the server side validation against it? This case how can I smoke test if validation is in effect or not?
Sample Code
@page
@model TestFormModel
@{
ViewData["Title"] = "Home page";
}
<div class="text-center">
<form method="post">
<input type="text" name="myinput"/>
<input type="submit" value="Submit" />
</form>
</div>
//[AutoValidateAntiforgeryToken]
public class TestFormModel : PageModel
{
private readonly ILogger<TestFormModel> _logger;
public TestFormModel(ILogger<TestFormModel> logger)
{
_logger = logger;
}
public void OnGet()
{
}
public void OnPost()
{
}
}
Upvotes: 4
Views: 5327
Reputation: 87191
For the later Core versions (6,7 and maybe earlier), here's what the documentation states regarding when/if a token will be generated automatically:
The automatic generation of antiforgery tokens for HTML form elements happens when the
<form>
tag contains themethod="post"
attribute and either of the following are true:
- The action attribute is empty (
action=""
).- The action attribute isn't supplied (
<form method="post">
).
That mean that if to set a form's action
attribute to a custom value, the "Antiforgery" element won't be injected automatically.
Here are a few ways one can do in those cases to have one injected:
asp-antiforgery="true"
to the form
element@Html.AntiForgeryToken()
within the form
element@inject Microsoft.AspNetCore.Antiforgery.IAntiforgery Xsrf
to the view and<input id="__RequestVerificationToken" type="hidden" value="@Xsrf.GetAndStoreTokens(Context).RequestToken" />
within the form
elementsubmit
element's formaction
attribute instead of the form
's.Upvotes: 3
Reputation: 2090
For .Net 3.1 the form helper does add the validation token to forms when you use it like <form asp-action="...
With asp.net core 3.1 with a form that does not use asp-action and or asp-controller like:
<form asp-action="Index" asp-controller="Home" method="post">
and uses this:
<form action="Index" method="post">
To include this: (in the form {before the closing form: })
<input name="__RequestVerificationToken" type="hidden" value="..." />
I just add this to the form:
asp-antiforgery="true"
like:
<form action="Index" method="post" asp-antiforgery="true">
Always works for me
This does not work for me:
<input name="__RequestVerificationToken" type="hidden" value="{{token}}" />
I just get that exact thing which doesn't have the token. Of course you then need the decorator before your method like:
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Update(...
Hope that helps someone searching for how to include the RequestVerificationToken or ValidateAntiForgeryToken
Upvotes: 0
Reputation: 3821
Previously in .NET Framework versions of ASP.NET you did have to opt-in to anti-forgery token usually with an attribute.
[ValidateAntiForgeryToken]
public ActionResult Save(Product product)
{
db.Product.Add(product);
Return View();
}
In ASPNET Core this automagically included in the Form Tag Helper. So any time your CSHTML includes a FORM element, the hidden field is included for you by the ASPNET Core runtime.
The basis for including this by default is the mantra of "Convention over configuration". By convention, 80+% of developers would opt to protect their application against CSRF attacks. If you wish to go against the convention, you can find the option to opt out in the conventions helper in the ConfigureServices
portion of your Startup class.
public void ConfigureServices(IServiceCollection services)
{
services.AddRazorPages()
.AddRazorPagesOptions(options =>
{
options.Conventions
.ConfigureFilter(new IgnoreAntiforgeryTokenAttribute());
});
}
This blog post goes in further detail specific to Razor Pages, options and usage scenarios.
If you read the a code, you may notice that there is no taghelper. – g.pickardou
There is indeed a tag helper. In a new Razor Pages project template you can find the tag helpers are included in the _ViewImports.cshtml
file here:
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
We can validate that your <form />
element, as written in the OP is invoking an ASP.NET tag helper as follows:
<form method="post">
<input type="text" name="myinput"/>
<input type="submit" value="Submit" />
</form>
If we inspect the page source on this, you will see the result
<form method="post">
<input type="text" name="myinput" />
<input type="submit" value="Submit" />
<input name="__RequestVerificationToken" type="hidden" value="{{token}}" />
</form>
Now, if we use the syntax to opt out of individual tag helpers
<!form method="post">
<input type="text" name="myinput" />
<input type="submit" value="Submit" />
</!form>
And again inspect the page source we can clearly see we have explicitly opted out of this tag helper.
<form method="post">
<input type="text" name="myinput" />
<input type="submit" value="Submit" />
</form>
Upvotes: 9