Antiforgery middleware#38314
Conversation
There was a problem hiding this comment.
It seemed like doing a ProblemDetails would be a possible thing to do here. The current filter in MVC simply returns a status code but it felt like we could offer more details.
The interesting bit to note is that these requests should have primarily been triggered by a browser POST so returning JSON is a bit unusual.
There was a problem hiding this comment.
Seems wrong to be forcibly returning JSON here. Why wouldn't we just let it throw or throw BadHttpRequestException or something else to enable the app to handle how this responds to the client?
d738fe9 to
5e7e71b
Compare
| private readonly RequestDelegate _next; | ||
| private readonly ILogger<AntiforgeryMiddleware> _logger; | ||
|
|
||
| public AntiforgeryMiddleware(IAntiforgery antiforgery, RequestDelegate next, ILogger<AntiforgeryMiddleware> logger) |
There was a problem hiding this comment.
Is this middleware important enough to be included in security check in EndpointMiddleware?
aspnetcore/src/Http/Routing/src/EndpointMiddleware.cs
Lines 38 to 42 in bc118a3
There was a problem hiding this comment.
Yup, that's on my list of things to do. We also need to add a StartupAnalyzer that suggests ordering this after Routing and AuthZ middlewares.
| else | ||
| { | ||
| Log.AntiforgeryValidationFailed(_logger, message); | ||
| await context.Response.WriteAsJsonAsync(new ProblemDetails |
There was a problem hiding this comment.
Any reason this doesn't set the status code to 400 or call WriteAntiforgeryInvalidResponseAsync?
|
@Tratcher pointed out that we should be applying the form limits before this middleware is executed. In MVC, this is currently implemented as a separate auth filter: https://github.com/dotnet/aspnetcore/blob/main/src/Mvc/Mvc.Core/src/RequestFormLimitsAttribute.cs, https://github.com/dotnet/aspnetcore/blob/main/src/Mvc/Mvc.Core/src/Filters/RequestFormLimitsFilter.cs. Would we want to roll these two things in to a separate /cc @DamianEdwards in case you wanted to chime in. |
|
Is the intent here to just have this middleware validate antiforgery tokens/cookies/headers if present in the request? i.e. issuing tokens and sending them back to the client is still up to the framework or manual app code. |
| return (true, null); | ||
| } | ||
|
|
||
| var tokens = await _tokenStore.GetRequestTokensAsync(httpContext); |
There was a problem hiding this comment.
Something should catch the AntiforgeryValidationException and convert it to a 400.
Today, Antiforgery is implemented as a filter in MVC. There's an attribute that also acts as an auth filter. It reads the form and performs a validation. Razor Pages add an implicit antiforgery filter that is active for all non-idempotent (POST / PUT / DELETE etc) requests. We'd like to enable Antiforgery to become available outside of MVC. My goal was to continue relying on these attributes, but as metadata that indicated if the user intended to perform antiforgery validation for that endpoint. In minimal endpoints, this might look like: app.MapPost("/post", (IFormFile formFile) => { ... })
.ValidateAntiforgery(); // Maybe we can infer this based on the presence of things that come from a HTTP form.Generating the antiforgery token that goes in to the form is still tied to the app framework. MVC will generate if you're using the form tag helper / Html.BeginForm(). For a form post using minimal, a user can use the |
No description provided.