400 status code when using AutoValidateAntiforgeryTokenAttribute
dotnetspark opened this issue · comments
I want to exclude some endpoints from being checked for antiforgery (GET only). Hence, I'm using the following,
services.AddControllers(options =>
{
options.Filters.Add(new AutoValidateAntiforgeryTokenAttribute());
});
According to the AutoValidateAntiforgeryTokenAuthorizationFilter implementation, GET will be excluded from checking antiforgery. However, after I'm logged on, the following request is a POST and I get a 400. Somehow, when I remove the above filter then app works as usual. The reason I needed to add that filter was because AsBffApiEndpoint()
is requiring antiforgery header in all endpoints, and I need some of them to be bypassed.
Also, in Blazor6 sample code I see MapRemoteBffApiEndpoint(...).RequireAccessToken(TokenType.UserOrClient)
is not being used. Is this the new pattern?
Our BFF doesn't use the ASP.NET Core anti-forgery mechanism. We describe here how it works in our library.
Indeed. I just got 401 for bff/user which is a GET. Then I got the 400 Bad Request - Request Too Long. Meaning if I want to bypass Antiforgery check on all GET endpoints, how should I do it?
You can flag any endpoints that you want to exclude from antiforgery with our attribute
[BffApi(requireAntiForgeryCheck = false)]
Great. Now, I'm trying to find a way to not add it manually. Somehow to use AssBffApiEndpoint(false)
on the list of endpoints I need
I've tried to use the following but didn't work. I get a 401 if I don't pass the header.
var requireAntiForgeryCheck = true;
app.Use(async (context, next) =>
{
var endpoint = context.GetEndpoint();
var getAttribute = endpoint.Metadata.GetMetadata<HttpGetAttribute>();
if (getAttribute != null)
{
var bffApiAttribute = endpoint.Metadata.GetMetadata<BffApiAttribute>();
if (bffApiAttribute != null)
{
var routeAttribute = endpoint.Metadata.GetMetadata<RouteAttribute>();
if (routeAttribute != null && routeAttribute.Template.StartsWith("api/internal")l)
{
requireAntiForgeryCheck = false;
}
}
}
await next();
});
app.UseAuthentication();
app.UseBff();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapBffManagementEndpoints();
endpoints.MapControllers().RequireAuthorization().AsBffApiEndpoint(requireAntiForgeryCheck);
});
I figured it out. See below.
public static TBuilder AsBffApiEndpointBypassAntiforgeryOnGET<TBuilder>(this TBuilder builder, string routePrefix) where TBuilder : IEndpointConventionBuilder
{
builder.Add(endpointBuilder =>
{
var getAttribute = endpointBuilder.Metadata.FirstOrDefault(m => m.GetType() == typeof(HttpGetAttribute)) as HttpGetAttribute;
var routeAttribute = endpointBuilder.Metadata.FirstOrDefault(m => m.GetType() == typeof(RouteAttribute)) as RouteAttribute;
if (getAttribute != null && routeAttribute != null && routeAttribute.Template.StartsWith(routePrefix))
{
endpointBuilder.Metadata.Add(new BffApiAttribute(false));
}
else
{
endpointBuilder.Metadata.Add(new BffApiAttribute(true));
}
});
return builder;
}
Then in Startup.cs
app.UseEndpoints(endpoints =>
{
endpoints.MapBffManagementEndpoints();
endpoints.MapControllers().RequireAuthorization().AsBffApiEndpointBypassAntiforgeryOnGET("api/Foo");
});
This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue.