How can we protect our application, even though we are still leveraging client-side logic while retaining the security of the application? The problem can be resolved in two ways: one is to perform anti-forgery token verification (making sure that the transmitted data has not been tampered with) and the other is to validate the model again in the server side (double-checking ensures that the model is still safe).
A pure MVC Core web application that uses an MVC templating engine can perform the anti-forgery verification in a straightforward manner. MVC generates the anti-forgery token by default for us and all we have to do is verify it at the server side. We could still configure the view to support anti-forgery token generation by enabling asp-antiforgery in the <form> tag, as follows:
<form asp-action="Create" asp-antiforgery="true">
<div class="form-horizontal">
...
The old-fashioned way of generating an anti-forgery token is still available and can be done in the following way:
<form asp-action="Create">
@Html.AntiForgeryToken()
<div class="form-horizontal">
...
The anti-forgery token can be validated in the server side by configuring it using the custom ValidateAntiForgeryToken attribute on the action level:
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create(User user)
The anti-forgery token can be validated in the server side by configuring it using the custom AutoValidateAntiForgeryToken attribute on the controller level:
[AutoValidateAntiForgeryToken]
public class UsersController : Controller
The same verification can also be done on a global level using AutoValidateAntiforgeryTokenAttribute configured in StartUp.cs inside the ConfigureServices() method, as follows:
public void ConfigureServices(IServiceCollection services)
{
// Add framework services.
services.AddDbContext<BlogContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString
("DefaultConnection")));
services.AddMvc(options =>
options.Filters.Add(new AutoValidateAntiforgeryTokenAttribute()));
services.AddAuthorization(options =>
{
options.AddPolicy("Administrators", policy =>
policy.RequireRole("Administrators"));
});
}
An AngularJS templating engine works a little different in processing the anti-forgery; it uses the XSRF-TOKEN cookie to address the issue. We have a provision in MVC to configure and send the information that would be leveraged by the AngularJS $http service. Exploring those details would be out of context for this book, so just know that we have a provision to use them in a pure JavaScript templating engine as well.
We have figured out how the client-side validation is shielded from attacks; now let's look at the manual validation in the next section.