| File: Integration\BlazorWebSocketOriginTests.cs | Web Access |
| Project: src\tests\Aspire.Dashboard.Tests\Aspire.Dashboard.Tests.csproj (Aspire.Dashboard.Tests) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Net; using System.Net.WebSockets; using Microsoft.AspNetCore.InternalTesting; using Xunit; namespace Aspire.Dashboard.Tests.Integration; public class BlazorWebSocketOriginTests(ITestOutputHelper testOutputHelper) { [Theory] [InlineData(null, "/_blazor")] [InlineData("https://evil.example.com", "/_blazor")] [InlineData("https://evil.example.com", "/_blazor/")] public async Task BlazorWebSocket_InvalidOrigin_ReturnsForbidden(string? origin, string path) { await using var app = IntegrationTestHelpers.CreateDashboardWebApplication(testOutputHelper); await app.StartAsync().DefaultTimeout(); var frontendUri = new Uri(app.FrontendSingleEndPointAccessor().GetResolvedAddress()); using var client = new HttpClient { BaseAddress = frontendUri }; using var request = CreateWebSocketUpgradeRequest(origin, path); using var response = await client.SendAsync(request).DefaultTimeout(); Assert.Equal(HttpStatusCode.Forbidden, response.StatusCode); Assert.Equal("Origin not allowed.", await response.Content.ReadAsStringAsync()); } [Fact] public async Task BlazorWebSocket_SameOrigin_UpgradeSucceeds() { await using var app = IntegrationTestHelpers.CreateDashboardWebApplication(testOutputHelper); await app.StartAsync().DefaultTimeout(); var frontendUri = new Uri(app.FrontendSingleEndPointAccessor().GetResolvedAddress()); using var client = new ClientWebSocket(); client.Options.SetRequestHeader("Origin", frontendUri.GetLeftPart(UriPartial.Authority)); await client.ConnectAsync(CreateWebSocketUri(frontendUri), CancellationToken.None).DefaultTimeout(); Assert.Equal(WebSocketState.Open, client.State); await client.CloseAsync(WebSocketCloseStatus.NormalClosure, "Test complete", CancellationToken.None).DefaultTimeout(); } private static HttpRequestMessage CreateWebSocketUpgradeRequest(string? origin, string path) { var request = new HttpRequestMessage(HttpMethod.Get, path) { Version = HttpVersion.Version11, VersionPolicy = HttpVersionPolicy.RequestVersionExact }; request.Headers.TryAddWithoutValidation("Connection", "Upgrade"); request.Headers.TryAddWithoutValidation("Upgrade", "websocket"); request.Headers.TryAddWithoutValidation("Sec-WebSocket-Version", "13"); request.Headers.TryAddWithoutValidation("Sec-WebSocket-Key", "dGhlIHNhbXBsZSBub25jZQ=="); if (origin is not null) { request.Headers.TryAddWithoutValidation("Origin", origin); } return request; } private static Uri CreateWebSocketUri(Uri frontendUri) { return new UriBuilder(frontendUri) { Scheme = frontendUri.Scheme == Uri.UriSchemeHttps ? "wss" : "ws", Path = "/_blazor" }.Uri; } }