dotnet / aspnetcore

ASP.NET Core is a cross-platform .NET framework for building modern cloud-based web applications on Windows, Mac, or Linux.
https://asp.net
MIT License
35.25k stars 9.96k forks source link

400 Bad request, A valid antiforgery token was not provided with the request. - Still not fixed .net 8 #56325

Closed htmlsplash closed 3 months ago

htmlsplash commented 3 months ago

Is there an existing issue for this?

Describe the bug

When user authenticates and submits a form using Editform component in SSR page, the page will respond with:

A valid antiforgery token was not provided with the request. Add an antiforgery token, or disable antiforgery validation for this endpoint. In live deployment, you get 400 bad request.

Caused by app.UseAntiforgery(); being registered before app.UseAuthentication(); app.UseAuthorization();

Original reported issue: https://github.com/dotnet/aspnetcore/issues/50612,

Supposedly fixed at: https://github.com/dotnet/aspnetcore/issues/50818

Well, it is not fixed. If I register antiforgery before authentication/authorization, you still get the error. Am I doing something wrong here?

Additional problem discovered: NOTE: Here I do have antiforgery middleware after auth/authorize middleware but doesn't work correctly.

If you open 2 tabs in the browser: 1 tab with the submission form, the other tab (tab 2) with another page where the user can log out. Then, when user logs out from tab 2 and then you switch to tab 1 with the EditForm, fill it out, and submit the form, your receive error:

400 Bad request, A valid antiforgery token was not provided with the request.

This problem also happens if you go from unauthenticated user to authenticated user. Basically, when authentication state changes (logged in to logged out or logged out to logged in), you cannot submit the form.

This page does not have an authorized attribute or use authorization.

Expected Behavior

See comments in description.

Steps To Reproduce

No response

Exceptions (if any)

No response

.NET Version

No response

Anything else?

No response

halter73 commented 3 months ago

Additional problem discovered: NOTE: Here I do have antiforgery middleware after auth/authorize middleware but doesn't work correctly.

If you open 2 tabs in the browser: 1 tab with the submission form, the other tab (tab 2) with another page where the user can log out. Then, when user logs out from tab 2 and then you switch to tab 1 with the EditForm, fill it out, and submit the form, your receive error:

400 Bad request, A valid antiforgery token was not provided with the request.

This problem also happens if you go from unauthenticated user to authenticated user. Basically, when authentication state changes (logged in to logged out or logged out to logged in), you cannot submit the form.

This page does not have an authorized attribute or use authorization.

It sounds like you've resolved your main issue by putting UseAntiforgery() after UseAuthentication() and UseAuthorization(). The behavior you're seeing where forms get 400 responses if the user changed between rendering and submitting the form is by design. While it's an unfortunate user experience, antiforgery tokens for different or anonymous users must be rejected, because otherwise an attacker could request an antiforgery token for their use (or an anonymous user) and use it to execute a CSRF attack using a victim's browser and cookies.

It doesn't matter if the page has an [Authorize] attribute. The framework has to assume that the application might be trusting HttpContext.User. If the form post really does the same thing no matter who submits it, you might consider doing a normal <form method="get"... (which could be better for forward and backward navigation for things like search boxes) or mark the page with @attribute [IgnoreAntiforgeryToken].

If the form post is for a specific user, the form must be reloaded with new valid antiforgery tokens when the user changes before the form post works in order for it to be secure. If you are still having issues, we will need a repro project demonstrating the issue.

htmlsplash commented 3 months ago

Thank you for filing this issue. In order for us to investigate this issue, please provide a minimal repro project that illustrates the problem without unnecessary code. Please share with us in a public GitHub repo because we cannot open ZIP attachments, and don't include any confidential content.

I believe I shared enough information to reproduce the issue. Any sample project template Blazor Webapp (.net 8, Server (static SSR by default), interactivity per page/component) should work. I am not that savvy with putting things on github.

MackinnonBuck commented 3 months ago

We do acknowledge that the user experience in this scenario can be less than ideal. However, the behavior you're experiencing is by design. Therefore, we're going to close out this issue since there isn't anything we intend to change in this area.