Anti-CSRF protection in ASP.Net Core
In this article, I have given the reason why it is necessary to globally apply protection against CSRF attacks for all HTTP requests using the POST method. Throughout this article I talk about Anti-CSRF protection in ASP.Net Core.
The reason is to avoid the developer forgetting to use the ValidateAntiForgeryToken filter when it codes the actions of the controllers that must receive HTTP POST requests.
in an ASP.Net Core application no need to use the filter provider code ValidateAntiForgeryTokenProvider even less to use the attribute DisableValidateAntiForgeryToken (read the article cited above to see what these classes are for). These classes are no longer useful when you use ASP.Net Core technology since it came with more or less identical techniques to do exactly the same. This is code to remove if you are in the process of or have planned to migrate an application using ASP.Net MVC.
The filters AutoValidateAntiforgeryToken and IgnoreAntiforgeryToken
ASP.Net Core has come with new attributes to overcome this shortcoming with ASP.Net MVC. In addition to always having the filter ValidateAntiForgeryToken (a filter of the same name already exists with ASP.Net MVC), we have two new filters: AutoValidateAntiforgeryToken and IgnoreAntiforgeryToken whose respective declarations are:
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple=false, Inherited=true)] public class AutoValidateAntiforgeryTokenAttribute : Attribute, IFilterFactory, IOrderedFilter [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple=false, Inherited=true)] public class IgnoreAntiforgeryTokenAttribute : Attribute, IOrderedFilter, IAntiforgeryPolicy
It is not a filter provider as it was in the solution I in ASP.Net MVC technology. We have at our disposal the AutoValidateAntiforgeryToken filter which does not only validate HTTP POST requests but takes into account all HTTP methods except GET, HEAD, OPTIONS and TRACE methods.
This filter can be applied:
- at the level of one or more actions of a controller : to note that this brings no more compared to the direct use of the filter ValidateAntiForgeryToken . As a reminder, the purpose of this article is to avoid any forgetfulness of the developer to place the filter to validate the anti-CSRF validation token.
- at the level of the controller class : since a well-executed application very rarely contains a single controller then the risk of forgetting mentioned in the previous point is always present.
- globally to the whole application : the risk related to the forgetfulness of the developer is equal to zero
In my applications, you will understand, I will focus on the overall configuration. This configuration is done in the ConfigureServices method of the Startup class of our ASP.Net Core application. Whether our project follows the MVC application template or the latest Razor Pages, the configuration will always be via the AddMvc method AddMvc as below:
services.AddMvc(options => options.Filters.Add(new AutoValidateAntiforgeryTokenAttribute()));
With this central configuration, the POST type actions can be written as the sample code below, where we note the complete absence of the ValidateAntiForgeryToken filter:
[HttpPost] public async Task<IActionResult> Create(PersonViewModel model) { // [...] }
In ASP.Net MVC I included an attribute called DisableValidateAntiForgeryToken that allows exceptions for certain HTTP POST requests applied to actions whose execution does not. is not at all risky therefore mainly actions where we do not need the user to be authenticated. With ASP.Net Core, the IgnoreAntiforgeryToken attribute allows you to do exactly the same IgnoreAntiforgeryToken . In your ASP.Net Core application, once the global configuration of the CSRF protection has been applied, all you have to do is list the actions to exclude and decorate them with the IgnoreAntiforgeryToken filter. Below is an example of an action in a controller with the attribute IgnoreAntiforgeryToken :
[HttpPost] [IgnoreAntiforgeryToken] public async Task<IActionResult> MonAction(MonViewModel model) { // [...] }