'ValidateAntiForgeryToken 400 error Using angular 13 and ASP.NET core 5
I am using Angular 13 and ASP.Net Core5. I am trying to use ValidateAntiFOrgeryToken attribute and always get 400 error. Before I post this question, I tried almost all the solutions found on the internet. But, I want to clarify my case, I am creating a multi-tenant app. Every business owner will have a subdomain and separate database. I don't know if the Antiforgery token is not working due to this condition or not, but I tried many solutions for 3 days.
Startup.cs
services.AddAntiforgery(options =>
{
options.Cookie.Name = "XSRF-TOKEN";
options.HeaderName = "X-XSRF-TOKEN";
options.Cookie.HttpOnly = false;
});
I used this configuration and ASP.NET sent antiforgery cookie with the name XSRF-TOKEN. According the Angular documentation, Angular will sent a header with name X-XSERF-TOKEN if there is a cookie with the name X-XSRF-TOKEN. Actually, Angular sent it successfully with every request, but I still getting error with code 400.
I tried to add the X-XSRF-TOKEN manually. I tried to use following a middlewhere
app.Use(next => context =>
{
if (
string.Equals(context.Request.Path.Value, "/", StringComparison.OrdinalIgnoreCase) ||
string.Equals(context.Request.Path.Value, "/index.html", StringComparison.OrdinalIgnoreCase) ||
string.Equals(context.Request.Path.Value, "/api", StringComparison.OrdinalIgnoreCase))
{
// We can send the request token as a JavaScript-readable cookie, and Angular will use it by default.
var tokens = antiForgery.GetAndStoreTokens(context);
context.Response.Cookies.Append("XSRF-TOKEN", tokens.RequestToken,
new CookieOptions() { HttpOnly = false, Secure = false });
}
return next(context);
});
I tried to use CORS in startup.cs
services.AddCors(c => { c.AddPolicy("AllowOrigin", options => options.AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod()); });
app.UseCors(policy =>
{
policy.AllowAnyOrigin();
policy.AllowAnyHeader();
policy.AllowAnyMethod();
});
then added [EnableCors(PolicyName = "AllowOrigin")] for the controller.
I tried combinations of these solutions but I am still getting the same error.
Solution 1:[1]
Finally, I figured out the problem. My case is that I create a subdomain and different database for each business owner. The [ValidateAntiForgeryToken] works well with the following configuration:
in ConfigureServices:
services.AddAuthentication(x =>
{
x.DefaultAuthenticateScheme = IdentityConstants.ApplicationScheme;
x.DefaultChallengeScheme = IdentityConstants.ApplicationScheme;
})
.AddCookie(IdentityConstants.ApplicationScheme)
.AddJwtBearer(x =>
{
x.RequireHttpsMetadata = false;
x.TokenValidationParameters = new TokenValidationParameters()
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["TokenKey"])),
ValidateIssuer = false,
ValidateAudience = false
};
});
In Configure:
app.Use(next => context =>
{
if (context.Request.Path.Value.IndexOf("/api", StringComparison.OrdinalIgnoreCase) != -1)
{
var tokens = antiForgery.GetAndStoreTokens(context);
context.Response.Cookies.Append("XSRF-TOKEN", tokens.RequestToken,
new CookieOptions() { HttpOnly = false, Secure = false });
}
return next(context);
});
However, this works will without the Authorize attribute [Authorize].
So, my solution to use [Authorize] and [ValidateAntiForgeryToken] is to create a custom Antiforgery token attribute.
I created the custom AntiForgeryToken using the solution in this question
https://stackoverflow.com/a/28526906/14474303.
But be carefull, If your controller class inherits from ControllerBase, this means you using Microsoft.AspNetCore.Mvc;, but if it inherits from ApiController, then, you are using System.Web.Http. The solution in this link is using System.Web.Http and it will not work if you are using `Microsoft.AspNetCore.Mvc.
Simply, if you will create a custom Antiforgery token, your custom class will inherits from ActionFilterAttribute. So, if you are using System.Web.Http, then ActionFilterAttribute will be imported from System.Web.Http, but, it you are using Microsoft.AspNetCore.Mvc, then ActionFilterAttribute will be imported from `Microsoft.AspNetCore.Mvc.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |
