Anti-Forgery Token Issue in ASP.NET Core 2.1+ Applications
Environment
Product | Progress® Telerik® Reporting |
Project Type | ASP.NET Core, ASP.NET Core MVC |
Viewer Type | HTML5 Report Viewer |
Description
When adding any of the following lines of code in the Startup.cs
file, the report won't load and an error will be thrown.
Error Messages
One of the following error messages may occur:
services.AddMvc(options =>
options.Filters.Add(new Microsoft.AspNetCore.Mvc.AutoValidateAntiforgeryTokenAttribute()));
or
services.AddControllersWithViews(options =>
options.Filters.Add(new Microsoft.AspNetCore.Mvc.AutoValidateAntiforgeryTokenAttribute()));
Steps to Reproduce
-
Implement the anti-forgery token. For example, in ASP.NET Core MVC application, create a new
GetAntiXsrfRequestToken()
function on the viewer page to get the request token:@inject Microsoft.AspNetCore.Antiforgery.IAntiforgery Xsrf @functions{ public string GetAntiXsrfRequestToken() { return Xsrf.GetAndStoreTokens(Context).RequestToken; } }
-
Add the function to each request header:
<script type="text/javascript"> $.ajaxPrefilter(function (options, originalOptions, jqXHR) { jqXHR.setRequestHeader("__RequestVerificationToken", '@GetAntiXsrfRequestToken()'); }); </script>
As a result the viewer shows the exception message Error registering the viewer with the service.
.
And, in the browser console the Register Client request returns 400 Bad Request
with the following error message:
Failed to load resource: the server responded with a status of 400 (Bad Request)
Uncaught (in promise) Invalid clientID
Solutions
The AutoValidateAntiforgeryToken
is recommended by Microsoft for non-API scenarios. When using this approach, that requires manually adding anti-forgery attributes. If you forget the attribute, no error will occur and the Controller
/Action
will not be protected. For that reason, the automatic approach is generally less error-prone and easier to maintain, especially if there are large number of Controllers and Actions that need this protection. You can use the AutoValidateAntiforgeryToken
with the ReportsController
provided that you do one of the following things:
-
Add the
IgnoreAntiforgeryToken
attribute to the ReportsController. For example:[Route("api/reports")] [IgnoreAntiforgeryToken] public class ReportsController : ReportsControllerBase { //... }
-
Override all
ReportsController
public methods and add theIgnoreAntiforgeryToken
attribute to them. You may skip theGET
HTTP methods.[IgnoreAntiforgeryToken] public override IActionResult RegisterClient() { return base.RegisterClient(); }
Alternatively, remove the auto anti-forgery configuration and decorate each controller or action that has to be protected against anti-forgery with the AutoValidateAntiforgeryToken
or ValidateAntiforgeryToken
attribute.
The following configuration or its equivalent:
services.AddMvc(options => { options.Filters.Add(new AutoValidateAntiforgeryTokenAttribute()); });
have to be replaced with the configuration:
services.AddMvc();
services.AddAntiforgery(options => options.HeaderName = "__RequestVerificationToken");