diff --git a/src/SignalR/common/Http.Connections/src/Internal/HttpConnectionDispatcher.cs b/src/SignalR/common/Http.Connections/src/Internal/HttpConnectionDispatcher.cs index ea0bee5bb799bed1af7c8bb24d2459f864d1bc80..bc495da58c1d8e14ebfed57e8195d17f908bf369 100644 --- a/src/SignalR/common/Http.Connections/src/Internal/HttpConnectionDispatcher.cs +++ b/src/SignalR/common/Http.Connections/src/Internal/HttpConnectionDispatcher.cs @@ -504,7 +504,7 @@ namespace Microsoft.AspNetCore.Http.Connections.Internal // We specifically clone the identity on first poll if it's a windows identity // If we swapped the new User here we'd have to dispose the old identities which could race with the application // trying to access the identity. - if (context.User.Identity is WindowsIdentity) + if (!(context.User.Identity is WindowsIdentity)) { existing.User = context.User; } diff --git a/src/SignalR/common/Http.Connections/test/HttpConnectionDispatcherTests.cs b/src/SignalR/common/Http.Connections/test/HttpConnectionDispatcherTests.cs index d79bcd3d9215fe3cc79d8c7d7de802ab93516e6d..d577a6a920c611d2726310ff1219a1c5469431c2 100644 --- a/src/SignalR/common/Http.Connections/test/HttpConnectionDispatcherTests.cs +++ b/src/SignalR/common/Http.Connections/test/HttpConnectionDispatcherTests.cs @@ -10,11 +10,10 @@ using System.Linq; using System.Net; using System.Net.WebSockets; using System.Security.Claims; +using System.Security.Principal; using System.Text; using System.Threading; using System.Threading.Tasks; -using Microsoft.AspNetCore.Authentication; -using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Connections; using Microsoft.AspNetCore.Connections.Features; using Microsoft.AspNetCore.Http.Connections.Internal; @@ -1347,6 +1346,55 @@ namespace Microsoft.AspNetCore.Http.Connections.Tests } } + [ConditionalFact] + [OSSkipCondition(OperatingSystems.Linux | OperatingSystems.MacOSX)] + public async Task LongPollingKeepsWindowsIdentityBetweenRequests() + { + using (StartVerifiableLog()) + { + var manager = CreateConnectionManager(LoggerFactory); + var connection = manager.CreateConnection(); + connection.TransportType = HttpTransportType.LongPolling; + var dispatcher = new HttpConnectionDispatcher(manager, LoggerFactory); + var context = new DefaultHttpContext(); + var services = new ServiceCollection(); + services.AddOptions(); + services.AddSingleton<TestConnectionHandler>(); + services.AddLogging(); + var sp = services.BuildServiceProvider(); + context.Request.Path = "/foo"; + context.Request.Method = "GET"; + context.RequestServices = sp; + var values = new Dictionary<string, StringValues>(); + values["id"] = connection.ConnectionId; + var qs = new QueryCollection(values); + context.Request.Query = qs; + + var builder = new ConnectionBuilder(sp); + builder.UseConnectionHandler<TestConnectionHandler>(); + var app = builder.Build(); + var options = new HttpConnectionDispatcherOptions(); + + var windowsIdentity = WindowsIdentity.GetAnonymous(); + context.User = new WindowsPrincipal(windowsIdentity); + + // would get stuck if EndPoint was running + await dispatcher.ExecuteAsync(context, options, app).OrTimeout(); + + Assert.Equal(StatusCodes.Status200OK, context.Response.StatusCode); + var currentUser = connection.User; + + var connectionHandlerTask = dispatcher.ExecuteAsync(context, options, app); + await connection.Transport.Output.WriteAsync(Encoding.UTF8.GetBytes("Unblock")).AsTask().OrTimeout(); + await connectionHandlerTask.OrTimeout(); + + // This is the important check + Assert.Same(currentUser, connection.User); + + Assert.Equal(StatusCodes.Status200OK, context.Response.StatusCode); + } + } + [Fact] public async Task SetsInherentKeepAliveFeatureOnFirstLongPollingRequest() {