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.34k stars 9.98k forks source link

Blazor, SignalR with Windows Auth, 401 error when using domain name listed in Intranet Zone site #31726

Closed tek-noid closed 3 years ago

tek-noid commented 3 years ago

.NET CORE 5.0 Blazer Server App, also running SignalR [Microsoft.AspNetCore.SignalR.Client 5.0.5] to push out changes.

Windows Auth enabled, Anonymous Disabled

Works fine on dev box (IIS Express & IIS) and on production server when BLUENET is used as the servername. BLUE.NET (note the period) is how users normally refer to it however, and we have this site listed in their Intranet zone and DNS pointing to the BLUENET server.

If you connect via BLUE.NET (note the period), the application works fine (i.e., Windows Auth credentials passed along transparently) for all endpoints except the two using SignalR. Those receive a 401.

Connect with BLUENET (no period) all endpoints (including the two SignalR endpoints) work fine.

Same behavior in Edge and Chrome.

Feels like SignalR isn't honoring the Intranet zone.

Blazor code

hub = new HubConnectionBuilder()
        .WithUrl(NavigationManager.ToAbsoluteUri("databasehub"), config =>
        {
            config.UseDefaultCredentials = true;

            config.HttpMessageHandlerFactory = innerHandler => new IncludeRequestCredentialsMessageHandler
            {
                InnerHandler = innerHandler
            };

        })
        .WithAutomaticReconnect()
        .Build();

        hub.On("OnDBhanged", async () =>
        {
            System.Diagnostics.Debug.WriteLine($"XXChanged");
            await Refresh();
        });

        await hub.StartAsync();

The HttpMessageHandlerFactory is simply some Dr. Google code that others claim solve the problem.

public class IncludeRequestCredentialsMessageHandler : DelegatingHandler
    {
        public IncludeRequestCredentialsMessageHandler()
        {
            InnerHandler = new HttpClientHandler()
            {
                Credentials = CredentialCache.DefaultNetworkCredentials,
                UseDefaultCredentials = true,
                PreAuthenticate = true
            };
        }

        protected override Task<HttpResponseMessage> SendAsync(
            HttpRequestMessage request, CancellationToken cancellationToken)
        {
            // The following SetBrowserRequestCredentials(...) api is not available for Blazor Server Side.
            //request.SetBrowserRequestCredentials(BrowserRequestCredentials.Include);

            return base.SendAsync(request, cancellationToken);
        }
    }
BrennanConroy commented 3 years ago

@pranavkm @javiercn How does Windows Auth work when invoking Http requests from a server-side component? I'm not sure there is anything SignalR specific here?

BrennanConroy commented 3 years ago

Triage: The customer might need to call RunImpersonated on the windows identity before creating the request in order to properly flow the windows identity.

BrennanConroy commented 3 years ago

Note: Windows auth + Chrome + WebSockets is known to have issues (doesn't work). This might also be true for Edge since it uses the same backend as Chrome. Have you tried other browsers?

tek-noid commented 3 years ago

I'm running the related IIS AppPool under an AD User if that helps.

I haven't tried another browser - now I'm using UrlRewrite to redirect people to the "intranet" site so the site works, so I'll need work out a test case.

Again, the Authentication flows correctly when the site is 'bluenet' but not 'blue.net' (DNS points each to the same server, no host headers).

BrennanConroy commented 3 years ago

the application works fine (i.e., Windows Auth credentials passed along transparently) for all endpoints except the two using SignalR

When you say this, are you referring to the browser connecting to the server working, or do you have other blazor components that make Http requests and those are working?

I'm not sure how familiar you are with how blazor works, but the components run on the server process, so any user intranet settings will not affect how the in process http requests behave.

Does the machine the server process is on have the BLUE.NET alias?

Can you confirm your host name is BLUENET?

BrennanConroy commented 3 years ago

We believe this scenario cannot work unless you impersonate the user that is calling the component that is running the hub connection. Impersonating the user can be done with RunImpersonated

ghost commented 3 years ago

This issue has been automatically marked as stale because it has been marked as requiring author feedback but has not had any activity for 4 days. It will be closed if no further activity occurs within 3 days of this comment. If it is closed, feel free to comment when you are able to provide the additional information and we will re-investigate.

See our Issue Management Policies for more information.

tek-noid commented 3 years ago

To close this out, I refactored the app to not use SignalR at all.

But, yes, DNS will resolve both blue.net and bluenet to the same IP (computer name is bluenet).

I can see how server-size blazor isn't going to understand user Intranet zone policies, though I'm 99% sure those are all set organization wide via GPO.

Anyway, again, no longer an issue due to refactoring, so moving on.

tek-noid commented 3 years ago

To close this out, I refactored the app to not use SignalR at all (outside of Blazor itself).

But, yes, DNS will resolve both blue.net and bluenet to the same IP (computer name is bluenet).

I can see how server-size blazor isn't going to understand user Intranet zone policies, though I'm 99% sure those are all set organization wide via GPO.

Anyway, again, no longer an issue due to refactoring, so moving on.