-
Notifications
You must be signed in to change notification settings - Fork 10.5k
Description
Is there an existing issue for this?
- I have searched the existing issues
Describe the bug
When using the AntiforgeryStateProvider class added #49108, it always returns null from GetAntiforgeryToken() on the Blazor Wasm side, after pre-rendering. I'm trying to use the token returned from this class to call an API controller that is annotated with [ValidateAntiForgeryToken].
Expected Behavior
GetAntiforgeryToken() should return a non null token.
Steps To Reproduce
In your Blazor page, Test.razor:
@inject AntiforgeryStateProvider Antiforgery
<button @onclick="GetAntiforgery">Get Antiforgery</button>
<pre>
@mDebug
</pre>
@code {
private string? mDebug;
private void GetAntiforgery()
{
mDebug = "Token: " + Antiforgery.GetAntiforgeryToken()?.Value;
}
}
In your .cshtml file that displays the pre-rendered component:
<component type="typeof(Test)" render-mode="WebAssemblyPrerendered" />
@section Scripts {
<script src="_framework/blazor.webassembly.js"></script>
}
<persist-component-state />
When you click the "Get Antiforgery" button, I would expect to see "Token: " followed by random digits. But was I actually see is just "Token: ".
Exceptions (if any)
N/A
.NET Version
8.0.100-rc.1.23463.5
Anything else?
The two relevant classes are:
DefaultAntiforgeryStateProvider- the implementation of theAntiforgeryStateProvideron the client side.EndpointAntiforgeryStateProvider- a subclassDefaultAntiforgeryStateProviderthat is used on the server side during pre-rendering.
It looks like the problem is DefaultAntiforgeryStateProvider only reads a value from PersistentComponentState in the constructor. _currentToken is readonly, so it is not possible for it get set in another way. EndpointAntiforgeryStateProvider is the only subclass of DefaultAntiforgeryStateProvider, but it has no way to communicate its token to its base class to be persisted.
When I change DefaultAntiforgeryStateProvider to call the virtual GetAntiforgeryToken() method to get the token to persist, the problem goes away, i.e. GetAntiforgeryToken() starts returning a non null token on the WebAssembly side:
Note that this only fixes components in render-mode="WebAssemblyPrerendered". I'm not sure how DefaultAntiforgeryStateProvider is supposed to work in render-mode="WebAssembly", as I don't think PersistentComponentState works in there.
In case it's helpful, here is the commit from my application where I use antiforgery: AustinWise/DinnerKillPoints@b8e4eff