admin管理员组文章数量:1122846
I want to customize the response received by the client when CSRF token validation fails. I was looking at ASP.NET's source code and found a middleware I think handles that.
By looking at it, I saw that it sets an IAntiForgeryValidationFeature
with an error when validation fails, so I created a middleware to check that.
public class CustomAntiForgeryValidationResponseMiddleware(RequestDelegate next)
{
public async Task InvokeAsync(HttpContext context)
{
IAntiforgeryValidationFeature? antiforgeryValidation = context.Features.Get<IAntiforgeryValidationFeature>();
if (antiforgeryValidation is not null && !antiforgeryValidation.IsValid)
{
context.Response.StatusCode = 403;
await context.Response.WriteAsJsonAsync(new ProblemDetails()
{
Title = "Forbidden",
Detail = "User is not allowed to perform this action",
Status = 403,
Extensions = new Dictionary<string, object?>()
{
{ "errors", new ApiError[] { new("Invalid or missing CSRF token") } }
}
});
}
await next(context);
}
}
I then added the middleware before the authentication one in the request pipeline.
app.UseMiddleware<CustomAntiForgeryValidationResponseMiddleware>();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();
app.Run();
However the feature is always null even on endpoints that require a CSRF token. What am I doing wrong?
I want to customize the response received by the client when CSRF token validation fails. I was looking at ASP.NET's source code and found a middleware I think handles that.
By looking at it, I saw that it sets an IAntiForgeryValidationFeature
with an error when validation fails, so I created a middleware to check that.
public class CustomAntiForgeryValidationResponseMiddleware(RequestDelegate next)
{
public async Task InvokeAsync(HttpContext context)
{
IAntiforgeryValidationFeature? antiforgeryValidation = context.Features.Get<IAntiforgeryValidationFeature>();
if (antiforgeryValidation is not null && !antiforgeryValidation.IsValid)
{
context.Response.StatusCode = 403;
await context.Response.WriteAsJsonAsync(new ProblemDetails()
{
Title = "Forbidden",
Detail = "User is not allowed to perform this action",
Status = 403,
Extensions = new Dictionary<string, object?>()
{
{ "errors", new ApiError[] { new("Invalid or missing CSRF token") } }
}
});
}
await next(context);
}
}
I then added the middleware before the authentication one in the request pipeline.
app.UseMiddleware<CustomAntiForgeryValidationResponseMiddleware>();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();
app.Run();
However the feature is always null even on endpoints that require a CSRF token. What am I doing wrong?
Share Improve this question asked Nov 21, 2024 at 12:02 iKingNinjaiKingNinja 3934 silver badges13 bronze badges2 Answers
Reset to default 1I solved the issue by creating a custom implementation of AutoValidateAntiforgeryTokenAttribute
which uses a custom implementation of ValidateAntiforgeryTokenAuthorizationFilter
which calls IAntiforgery.ValidateRequestAsync()
and writes the custom response body if it throws an exception.
It turned out that the antiforgery middleware was not running at all, but I'm not sure why (probably because the project was not a minimal API).
Generally, Anti-Forgery token validation failed will throw a 400 bad request error. Besides, if the request data invalid, it will also return a 400 bad request error.
So, before capturing the Anti-Forgery token validation exception, we need to know the Anti-Forgery Tokens workflow:
To help prevent CSRF attacks, ASP.NET MVC uses anti-forgery tokens, also called request verification tokens.
- The client requests an HTML page that contains a form. The server includes two tokens in the response. One token is sent as a cookie.
- The other is placed in a hidden form field. The tokens are generated randomly so that an adversary cannot guess the values. When the client submits the form, it must send both tokens back to the server.
- The client sends the cookie token as a cookie, and it sends the form token inside the form data. (A browser client automatically does this when the user submits the form.)
- If a request does not include both tokens, the server disallows the request.
So, you can try to use the UseStatusCodePages
method to capture the 400 error and check whether the request header or form contains the Anti-Forgery token: if the request header or form doesn't contain the Anti-Forgery token, this is a Anti-Forgery token exception, code as below:
app.UseStatusCodePages(async context =>
{
var response = context.HttpContext.Response;
if (response.StatusCode == 400 )
{
//check Anti-Forgery Tokens workflow: https://learn.microsoft.com/en-us/aspnet/web-api/overview/security/preventing-cross-site-request-forgery-csrf-attacks#anti-forgery-tokens
if (!context.HttpContext.Request.Headers.ContainsKey("RequestVerificationToken") & !context.HttpContext.Request.Form.ContainsKey("__RequestVerificationToken"))
{
//Anti-Forgery Tokens exceptions
response.StatusCode = StatusCodes.Status403Forbidden;
await response.WriteAsync("Antiforgery token validation failed.");
}
else
{
//other model validation error
await response.WriteAsync("Other 400 error.");
}
}
});
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthorization();
本文标签: cCustomize ASPNET Core39s AntiForgery failure responseStack Overflow
版权声明:本文标题:c# - Customize ASP.NET Core's AntiForgery failure response - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1736311107a1934620.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论