Skip to content

[Blazor] Antiforgery fix #50946

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Sep 27, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,9 @@ public DefaultAntiforgeryStateProvider(PersistentComponentState state)
// don't have access to the request.
_subscription = state.RegisterOnPersisting(() =>
{
state.PersistAsJson(PersistenceKey, _currentToken);
state.PersistAsJson(PersistenceKey, GetAntiforgeryToken());
return Task.CompletedTask;
}, new InteractiveAutoRenderMode());
}, RenderMode.InteractiveWebAssembly);

state.TryTakeFromJson(PersistenceKey, out _currentToken);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -896,6 +896,19 @@ public void FormNoAntiforgeryReturnBadRequest(bool suppressEnhancedNavigation)
DispatchToFormCore(dispatchToForm);
}

[Fact]
public void CanUseAntiforgeryTokenInWasm()
{
var dispatchToForm = new DispatchToForm(this)
{
Url = "forms/antiforgery-wasm",
FormCssSelector = "form",
InputFieldId = "Value",
SuppressEnhancedNavigation = true,
};
DispatchToFormCore(dispatchToForm);
}

[Theory]
[InlineData(true)]
[InlineData(false)]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
<Reference Include="Microsoft.AspNetCore.Authentication.Cookies" />
<Reference Include="Microsoft.AspNetCore.Components.WebAssembly.Server" />
<Reference Include="Microsoft.AspNetCore.Components.Server" />
<Reference Include="Microsoft.AspNetCore.Http.Results" />
<Reference Include="Microsoft.AspNetCore.Cors" />
<Reference Include="Microsoft.AspNetCore.Mvc" />
<Reference Include="Microsoft.AspNetCore.Components.Server" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
using Components.TestServer.RazorComponents.Pages.Forms;
using Components.TestServer.Services;
using Microsoft.AspNetCore.Components.WebAssembly.Server;
using Microsoft.AspNetCore.Mvc;

namespace TestServer;

Expand Down Expand Up @@ -149,6 +150,11 @@ private static void MapEnhancedNavigationEndpoints(IEndpointRouteBuilder endpoin
await response.WriteAsync("<html><body><h1>This is a non-Blazor endpoint</h1><p>That's all</p></body></html>");
});

endpoints.MapPost("api/antiforgery-form", ([FromForm] string value) =>
{
return Results.Ok(value);
});

static Task PerformRedirection(HttpRequest request, HttpResponse response)
{
response.Redirect(request.Query["external"] == "true"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
@page "/forms/antiforgery-wasm"
<h3>FormRunningOnWasmCanUseAntiforgeryToken</h3>

<TestContentPackage.WasmFormComponent/>
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
@attribute [RenderModeInteractiveWebAssembly]
@using Microsoft.AspNetCore.Components.Forms
@using System.Net.Http
<h3>WasmFormComponent</h3>

<form @formname="WasmForm" @onsubmit="SubmitForm">
<input id="Value" @bind="_value" name="Value" />
@if (OperatingSystem.IsBrowser())
{
<input id="send" type="submit" value="Send" />
}
<AntiforgeryToken />
</form>

@if (_posted)
{
@if (_succeeded)
{
<p id="pass">Posting the value succeded.</p>
}
else
{
<p>Posting the value failed.</p>
}
}
else
{
<p>Antiforgery: @_token</p>
}

@code {
string _value;
string _token;
bool _succeeded;
bool _posted;

[Inject] public AntiforgeryStateProvider AntiforgeryState { get; set; }
[Inject] public NavigationManager Navigation { get; set; }

protected override void OnInitialized()
{
if (OperatingSystem.IsBrowser())
{
var antiforgery = AntiforgeryState.GetAntiforgeryToken();
_token = antiforgery.Value;
}
}

private async Task SubmitForm()
{
if (OperatingSystem.IsBrowser())
{
var client = new HttpClient() { BaseAddress = new Uri(Navigation.BaseUri) };
var antiforgery = AntiforgeryState.GetAntiforgeryToken();
if (antiforgery != null)
{
_posted = true;
var request = new HttpRequestMessage(HttpMethod.Post, "api/antiforgery-form");
var content = new FormUrlEncodedContent(new KeyValuePair<string, string>[] { new ("Value", _value) });
request.Content = content;
request.Headers.Add("RequestVerificationToken", antiforgery.Value);
var response = await client.SendAsync(request);
if (response.IsSuccessStatusCode)
{
_succeeded = true;
}
else
{
_succeeded = false;
}
}
}
}
}