AspNetCore.Docs icon indicating copy to clipboard operation
AspNetCore.Docs copied to clipboard

Unable to implement SignalR Hub on IIS with windows authentification, works fine with IIS Express, negotiate fails 401 !

Open akaioda opened this issue 4 months ago β€’ 17 comments

Is there an existing issue for this?

  • [x] I have searched the existing issues

Describe the bug

Blazor Server application, SignalR hub fail in IIS environment. Works In development environment VS2022 with IIS Express !

Hubconnection.StartAsync() fail

Expected Behavior

Ability to establish connection to the hub from client connections with Windows authentication.

Hubconnection.StartAsync() should work.

Steps To Reproduce

https://github.com/akaioda/BlazorApp6

Exceptions (if any)

System.Net.Http.HttpRequestException: Response status code does not indicate success: 401 (Unauthorized). at System.Net.Http.HttpResponseMessage.EnsureSuccessStatusCode() at Microsoft.AspNetCore.Http.Connections.Client.HttpConnection.NegotiateAsync(Uri url, HttpClient httpClient, ILogger logger, CancellationToken cancellationToken) at Microsoft.AspNetCore.Http.Connections.Client.HttpConnection.GetNegotiationResponseAsync(Uri uri, CancellationToken cancellationToken) at Microsoft.AspNetCore.Http.Connections.Client.HttpConnection.SelectAndStartTransport(TransferFormat transferFormat, CancellationToken cancellationToken) at Microsoft.AspNetCore.Http.Connections.Client.HttpConnection.StartAsyncCore(TransferFormat transferFormat, CancellationToken cancellationToken) at Microsoft.AspNetCore.Http.Connections.Client.HttpConnection.StartAsync(TransferFormat transferFormat, CancellationToken cancellationToken) at Microsoft.AspNetCore.Http.Connections.Client.HttpConnectionFactory.ConnectAsync(EndPoint endPoint, CancellationToken cancellationToken) at Microsoft.AspNetCore.Http.Connections.Client.HttpConnectionFactory.ConnectAsync(EndPoint endPoint, CancellationToken cancellationToken) at Microsoft.AspNetCore.SignalR.Client.HubConnection.StartAsyncCore(CancellationToken cancellationToken) at Microsoft.AspNetCore.SignalR.Client.HubConnection.StartAsyncInner(CancellationToken cancellationToken) at Microsoft.AspNetCore.SignalR.Client.HubConnection.StartAsync(CancellationToken cancellationToken) at BlazorApp6.Components.Pages.Home.<OnInitializedAsync>b__6_0() in C:\Users\USER123456\source\repos\akaioda\BlazorApp6\Components\Pages\Home.razor:line 126 at BlazorApp6.Components.Pages.Home.OnInitializedAsync() in C:\Users\USER123456\source\repos\akaioda\BlazorApp6\Components\Pages\Home.razor:line 78 at Microsoft.AspNetCore.Components.ComponentBase.RunInitAndSetParametersAsync() at Microsoft.AspNetCore.Components.RenderTree.Renderer.GetErrorHandledTask(Task taskToHandle, ComponentState owningComponentState)

.NET Version

8.0.303

Anything else?

Notes : The network context is as follows. The Windows 2019 server is in a network zone that is accessed through a load balancer that provides SSL termination and carries the certificates. In my case, there is no load balancing per se, as there is only one target IIS 10 server, the environment is .net8, and it is a 100% intranet environment, including for clients. IIS is configured to use Windows authentication

Taken into account (see Home.razor) : SignalR negotiate fails from Blazor Server with windows authentication dotnet/aspnetcore#25000 [https://github.com/dotnet/aspnetcore/issues/25000#issuecomment-1877615925]

how to use impersonation when using Windows auth and SignalR from a Blazor Server app dotnet/aspnetcore#34618 [https://github.com/dotnet/AspNetCore.Docs/blob/main/aspnetcore/blazor/fundamentals/signalr.md]

Wireshark trace on IIS server (anonymized) : DOM\USER null at 704.

No.	 Time		Source			Destination		Protocol	Length	Info
393	 10.359434	LB_BOX_IPA.129	IIS_SRV_IPA.168	HTTP		951		GET / HTTP/1.1 
399	 10.591392	IIS_SRV_IPA.168	LB_BOX_IPA.129	HTTP		195		HTTP/1.1 401 Unauthorized  (text/html)
401	 10.619752	LB_BOX_IPA.129	IIS_SRV_IPA.168	HTTP		1034	GET / HTTP/1.1 , NTLMSSP_NEGOTIATE
402	 10.620323	IIS_SRV_IPA.168	LB_BOX_IPA.129	HTTP		890		HTTP/1.1 401 Unauthorized , NTLMSSP_CHALLENGE (text/html)
407	 10.627486	LB_BOX_IPA.129	IIS_SRV_IPA.168	HTTP		230		GET / HTTP/1.1 , NTLMSSP_AUTH, User: MYDOM\USER123456
482	 11.684344	IIS_SRV_IPA.168	LB_BOX_IPA.129	HTTP		59		HTTP/1.1 200 OK  (text/html)
484	 11.709732	LB_BOX_IPA.129	IIS_SRV_IPA.168	HTTP		1112	GET /app.css HTTP/1.1 
488	 11.712625	LB_BOX_IPA.131	IIS_SRV_IPA.168	HTTP		1126	GET /BlazorApp6.styles.css HTTP/1.1 
490	 11.712967	IIS_SRV_IPA.168	LB_BOX_IPA.131	HTTP		195		HTTP/1.1 401 Unauthorized  (text/html)
493	 11.722793	LB_BOX_IPA.131	IIS_SRV_IPA.168	HTTP		1209	GET /BlazorApp6.styles.css HTTP/1.1 , NTLMSSP_NEGOTIATE
494	 11.723268	IIS_SRV_IPA.168	LB_BOX_IPA.131	HTTP		890		HTTP/1.1 401 Unauthorized , NTLMSSP_CHALLENGE (text/html)
499	 11.724754	LB_BOX_IPA.132	IIS_SRV_IPA.168	HTTP		1115	GET /_framework/blazor.web.js HTTP/1.1 
501	 11.725033	IIS_SRV_IPA.168	LB_BOX_IPA.129	HTTP		1017	HTTP/1.1 200 OK  (text/css)
503	 11.725274	IIS_SRV_IPA.168	LB_BOX_IPA.132	HTTP		195		HTTP/1.1 401 Unauthorized  (text/html)
507	 11.725984	LB_BOX_IPA.131	IIS_SRV_IPA.168	HTTP		405		GET /BlazorApp6.styles.css HTTP/1.1 , NTLMSSP_AUTH, User: MYDOM\USER123456
513	 11.735904	IIS_SRV_IPA.168	LB_BOX_IPA.131	HTTP		311		HTTP/1.1 304 Not Modified 
517	 11.740033	LB_BOX_IPA.132	IIS_SRV_IPA.168	HTTP		1198	GET /_framework/blazor.web.js HTTP/1.1 , NTLMSSP_NEGOTIATE
518	 11.740419	IIS_SRV_IPA.168	LB_BOX_IPA.132	HTTP		890		HTTP/1.1 401 Unauthorized , NTLMSSP_CHALLENGE (text/html)
522	 11.744921	LB_BOX_IPA.132	IIS_SRV_IPA.168	HTTP		394		GET /_framework/blazor.web.js HTTP/1.1 , NTLMSSP_AUTH, User: MYDOM\USER123456
530	 11.753710	IIS_SRV_IPA.168	LB_BOX_IPA.132	HTTP		343		HTTP/1.1 304 Not Modified 
534	 11.808395	LB_BOX_IPA.132	IIS_SRV_IPA.168	HTTP		1049	GET /_blazor/initializers HTTP/1.1 
537	 11.816988	IIS_SRV_IPA.168	LB_BOX_IPA.132	HTTP/JSON	59		HTTP/1.1 200 OK , JSON (application/json)
539	 11.818836	LB_BOX_IPA.129	IIS_SRV_IPA.168	HTTP		1078	GET /favicon.ico HTTP/1.1 
541	 11.820223	IIS_SRV_IPA.168	LB_BOX_IPA.129	HTTP		59		HTTP/1.1 404 Not Found 
544	 11.834705	LB_BOX_IPA.132	IIS_SRV_IPA.168	HTTP		1267	POST /_blazor/negotiate?negotiateVersion=1 HTTP/1.1 
545	 11.846097	IIS_SRV_IPA.168	LB_BOX_IPA.132	HTTP/JSON	553		HTTP/1.1 200 OK , JSON (application/json)
550	 11.858801	LB_BOX_IPA.130	IIS_SRV_IPA.168	HTTP		1018	GET /_blazor?id=Zcwgu6iTkFOBbFhjzBnlBg HTTP/1.1 
552	 11.859234	IIS_SRV_IPA.168	LB_BOX_IPA.130	HTTP		195		HTTP/1.1 401 Unauthorized  (text/html)
554	 11.870701	LB_BOX_IPA.130	IIS_SRV_IPA.168	HTTP		1101	GET /_blazor?id=Zcwgu6iTkFOBbFhjzBnlBg HTTP/1.1 , NTLMSSP_NEGOTIATE
555	 11.871118	IIS_SRV_IPA.168	LB_BOX_IPA.130	HTTP		890		HTTP/1.1 401 Unauthorized , NTLMSSP_CHALLENGE (text/html)
558	 11.874242	LB_BOX_IPA.130	IIS_SRV_IPA.168	HTTP		297		GET /_blazor?id=Zcwgu6iTkFOBbFhjzBnlBg HTTP/1.1 , NTLMSSP_AUTH, User: MYDOM\USER123456
564	 11.888102	IIS_SRV_IPA.168	LB_BOX_IPA.130	HTTP		294		HTTP/1.1 101 Switching Protocols 
645	 12.166339	LB_BOX_IPA.129	IIS_SRV_IPA.168	HTTP		409		POST /chathub/negotiate?negotiateVersion=1 HTTP/1.1 
647	 12.166789	IIS_SRV_IPA.168	LB_BOX_IPA.129	HTTP		195		HTTP/1.1 401 Unauthorized  (text/html)
698	 12.204528	LB_BOX_IPA.129	IIS_SRV_IPA.168	HTTP		492		POST /chathub/negotiate?negotiateVersion=1 HTTP/1.1 , NTLMSSP_NEGOTIATE
699	 12.204986	IIS_SRV_IPA.168	LB_BOX_IPA.129	HTTP		890		HTTP/1.1 401 Unauthorized , NTLMSSP_CHALLENGE (text/html)
704	 12.207610	LB_BOX_IPA.129	IIS_SRV_IPA.168	HTTP		600		POST /chathub/negotiate?negotiateVersion=1 HTTP/1.1 , NTLMSSP_AUTH, User: \
706	 12.208425	IIS_SRV_IPA.168	LB_BOX_IPA.129	HTTP		195		HTTP/1.1 401 Unauthorized  (text/html)
1138 23.438988	LB_BOX_IPA.132	IIS_SRV_IPA.168	HTTP		413		POST /_blazor/disconnect HTTP/1.1 
1142 23.448608	IIS_SRV_IPA.168	LB_BOX_IPA.132	HTTP		59		HTTP/1.1 200 OK 

APP Log on IIS server :

2025-08-25 10:48:00.591 +02:00 [DBG] Registered SignalR Protocol: json, implemented by Microsoft.AspNetCore.SignalR.Protocol.JsonHubProtocol.
2025-08-25 10:48:00.592 +02:00 [DBG] Registered SignalR Protocol: blazorpack, implemented by Microsoft.AspNetCore.Components.Server.BlazorPack.BlazorPackHubProtocol.
2025-08-25 10:48:00.672 +02:00 [INF] Deferring to the server's implementation of Windows Authentication.
2025-08-25 10:48:00.723 +02:00 [INF] Application started. Press Ctrl+C to shut down.
2025-08-25 10:48:00.723 +02:00 [INF] Hosting environment: Production
2025-08-25 10:48:00.723 +02:00 [INF] Content root path: C:\inetpub\wwwroot\BlazorApp6
2025-08-25 10:48:00.747 +02:00 [INF] Request starting HTTP/1.1 GET http://myhost.mydomain.com/ - null null
2025-08-25 10:48:00.763 +02:00 [WRN] Failed to determine the https port for redirect.
2025-08-25 10:48:00.776 +02:00 [INF] Executing endpoint '/ (/)'
2025-08-25 10:48:00.926 +02:00 [INF] Executed endpoint '/ (/)'
2025-08-25 10:48:00.931 +02:00 [INF] Request finished HTTP/1.1 GET http://myhost.mydomain.com/ - 200 null text/html; charset=utf-8 184.8248ms
2025-08-25 10:48:00.953 +02:00 [INF] Request starting HTTP/1.1 GET http://myhost.mydomain.com/app.css - null null
2025-08-25 10:48:00.969 +02:00 [INF] Sending file. Request path: '/app.css'. Physical path: 'C:\inetpub\wwwroot\BlazorApp6\wwwroot\app.css'
2025-08-25 10:48:00.969 +02:00 [INF] Request finished HTTP/1.1 GET http://myhost.mydomain.com/app.css - 200 2154 text/css 15.6624ms
2025-08-25 10:48:00.975 +02:00 [INF] Request starting HTTP/1.1 GET http://myhost.mydomain.com/BlazorApp6.styles.css - null null
2025-08-25 10:48:00.978 +02:00 [INF] The file /BlazorApp6.styles.css was not modified
2025-08-25 10:48:00.978 +02:00 [INF] Request finished HTTP/1.1 GET http://myhost.mydomain.com/BlazorApp6.styles.css - 304 null text/css 3.1244ms
2025-08-25 10:48:00.994 +02:00 [INF] Request starting HTTP/1.1 GET http://myhost.mydomain.com/_framework/blazor.web.js - null null
2025-08-25 10:48:00.995 +02:00 [INF] Executing endpoint 'Blazor web static files'
2025-08-25 10:48:00.996 +02:00 [INF] The file /_framework/blazor.web.js was not modified
2025-08-25 10:48:00.996 +02:00 [INF] Executed endpoint 'Blazor web static files'
2025-08-25 10:48:00.996 +02:00 [INF] Request finished HTTP/1.1 GET http://myhost.mydomain.com/_framework/blazor.web.js - 304 null text/javascript 1.8019ms
2025-08-25 10:48:01.052 +02:00 [INF] Request starting HTTP/1.1 GET http://myhost.mydomain.com/_blazor/initializers - null null
2025-08-25 10:48:01.052 +02:00 [INF] Executing endpoint 'Microsoft.AspNetCore.Routing.RouteEndpoint'
2025-08-25 10:48:01.059 +02:00 [INF] Executed endpoint 'Microsoft.AspNetCore.Routing.RouteEndpoint'
2025-08-25 10:48:01.059 +02:00 [INF] Request finished HTTP/1.1 GET http://myhost.mydomain.com/_blazor/initializers - 200 null application/json; charset=utf-8 7.793ms
2025-08-25 10:48:01.062 +02:00 [INF] Request starting HTTP/1.1 GET http://myhost.mydomain.com/favicon.ico - null null
2025-08-25 10:48:01.063 +02:00 [INF] Request finished HTTP/1.1 GET http://myhost.mydomain.com/favicon.ico - 404 null null 0.7971ms
2025-08-25 10:48:01.063 +02:00 [INF] Request reached the end of the middleware pipeline without being handled by application code. Request path: GET http://myhost.mydomain.com/favicon.ico, Response status code: 404
2025-08-25 10:48:01.078 +02:00 [INF] Request starting HTTP/1.1 POST http://myhost.mydomain.com/_blazor/negotiate?negotiateVersion=1 - null 0
2025-08-25 10:48:01.080 +02:00 [INF] Executing endpoint 'Microsoft.AspNetCore.Routing.RouteEndpoint'
2025-08-25 10:48:01.084 +02:00 [DBG] New connection WDu9xVlBlaieev0XJetpaA created.
2025-08-25 10:48:01.088 +02:00 [DBG] Sending negotiation response.
2025-08-25 10:48:01.089 +02:00 [INF] Executed endpoint 'Microsoft.AspNetCore.Routing.RouteEndpoint'
2025-08-25 10:48:01.089 +02:00 [INF] Request finished HTTP/1.1 POST http://myhost.mydomain.com/_blazor/negotiate?negotiateVersion=1 - 200 316 application/json 10.3456ms
2025-08-25 10:48:01.124 +02:00 [INF] Request starting HTTP/1.1 GET http://myhost.mydomain.com/_blazor?id=Zcwgu6iTkFOBbFhjzBnlBg - null null
2025-08-25 10:48:01.124 +02:00 [INF] Executing endpoint 'Microsoft.AspNetCore.Routing.RouteEndpoint'
2025-08-25 10:48:01.127 +02:00 [DBG] Establishing new connection.
2025-08-25 10:48:01.130 +02:00 [DBG] OnConnectedAsync started.
2025-08-25 10:48:01.132 +02:00 [DBG] Socket opened using Sub-Protocol: 'null'.
2025-08-25 10:48:01.144 +02:00 [DBG] Found protocol implementation for requested protocol: blazorpack.
2025-08-25 10:48:01.147 +02:00 [DBG] Completed connection handshake. Using HubProtocol 'blazorpack'.
2025-08-25 10:48:01.172 +02:00 [DBG] Received hub invocation: InvocationMessage { InvocationId: "0", Target: "StartCircuit", Arguments: [ https://pecodsi.urssaf.recouv/, https://pecodsi.urssaf.recouv/, [], CfDJ8AZe+klKAG9FitXUnFgRJ3vRx6CLYzNV9Mpxn+sV5Pk4nwkrwSyrNwxHdjchdfUqdFl2gi7nO6q9cwwOXTrVQOew2XC4s6tY8aQY4es/enhFDv4e9xFmvoFzaWsUCcikqZp4VuXFRa4p2rofjUq+2ehumxMWwsCeKza4ssNDmUtj2nKCu8l5I25QsoMtVtg4Zmuus9yZqPKhLDvcbvv2+0K4nmVFqx+Ueo6c9rLaurJcmUYHW31rWHLnwQV9jMD9eTLbTRph1sKxm7UJqYF3ZUsH6qFaaJ6xvSCO32OWabZ7RiN1Yr3kk+D6jPrLI+LkO+dK3eLYvRQO8Sfw8Rnq8vuEMUai09D1snnA+dBVeF8w6iAda6pQ4osiSfBCGP1QAOiGgieeHMuE2VPVgqwvXJn17pq7o4MrBqts6vZ835vMkfRqMpQS9LvQfDkmKObu0kIV5IOrWMsP+gUp4iTpLToEYwNS6PGzI86tvjUdl2Oy1hre0jmisACZATrCTVirdpzPdI//JWukmxnGiM8Qc/4PwfkIRhwRes60fhFpgftlSmGVl4acJZuDAvqaDQl/vZdT7uXaCfm6NIp3qT9+oBbjv31Fb4xdANwxCwSyiTvU ], StreamIds: [  ] }.
2025-08-25 10:48:01.220 +02:00 [DBG] Received hub invocation: InvocationMessage { InvocationId: "", Target: "EndInvokeJSFromDotNet", Arguments: [ 2, True, [2,true,null] ], StreamIds: [  ] }.
2025-08-25 10:48:01.224 +02:00 [DBG] Received hub invocation: InvocationMessage { InvocationId: "", Target: "UpdateRootComponents", Arguments: [ {"batchId":1,"operations":[{"type":"add","ssrComponentId":1,"marker":{"type":"server","prerenderId":"22b64ae9dd414761871d614871e49c61","key":{"locationHash":"77D12F14A8105320B1AAED6AE7E689DA0EC4483270A645E84079EAA0FFDF550D:5","formattedComponentKey":""},"sequence":0,"descriptor":"CfDJ8AZe+klKAG9FitXUnFgRJ3vgFTb/BYgs+LbWgIqrgZ3r7X926o0YaU5XaoJqiWi1MTYVBV2RCXrOL0NM8fnADuQleSzSSV5e5JowBUSYF3oudAj/9LRzgaikJU6n9akUpkOSfD7lXXT3gGo58+TeXIrcdOkXkon/gmhT9PKISPgojY7cQkoDWYMGiU3nOTGdLYVhJ02BegK4UrG7lXViuTeBbbl5gh4EwmHlg8NWXVu24QTtcAA89kfRJD9anZ+nFE3DEJ08E7s+N5PQFK4g7MQkU98ZIhgv/YaCHF3emSZqAqFJn6FnfUsbvp12IYX1R7Tu5zfN/XxkZvk5XLoLqmerFYQlTVeV57qdEWN5EyZxj3gUTuYHkznJHAuLBh+Bf7nJL3bN5nbq+kMEYkVj9dqKVvyUmdfMIgO1Gkf3TTbqNa2GnSIys8cBbtQ5e0QtU2Zm6CmYPT31ab0JTbxULvYO+8o0+cR9evq1Uy1WrOlpoJpVS5a0YQCZJXYi0qbkOgiRt/+rB3/S10rPC88I9zOUn3YKaqJKYJOwL0Ql/m4hbXlkswrFobA+ITBXel5BILbsIFDIVA/iHdWE2T5Fh/E=","uniqueId":0}},{"type":"add","ssrComponentId":2,"marker":{"type":"server","key":{"locationHash":"302210BE96CD5C1828A8E2C33F34201FFDD2C760924B9C42E344BA402475A0DD:8","formattedComponentKey":""},"sequence":1,"descriptor":"CfDJ8AZe+klKAG9FitXUnFgRJ3sUMe79USccbhSVui0iOhNr2xGHHpJZXYxbh2z2/j3YhSbec+MiNbAOXM45AIP+4a1oppY0j2+w8R4OJt1g7OBo+owIgP3xzwGYN1pTY0brbbjDeoejLh1p0fsKCapbtQldtocxceXTMVzBNDXYG1guHFBx7qUP00NPuIwNVhpyPEttPmOxuprBAoCwPw7XMgepiNMJG56Wx1YvBUPohuJ+L8YZQxioRJUpzVKz1IG3WbdPIEBH19jXIahirfg+pZWTRC4RZlQYLQgMyarAIGpAXzyu4mSv7L0zzrbShVV3ofUOC9TUS7j8TCV8E16stQNorqT28d8Z8MjF/sxuu4i3zLZpb9NoSEHDqR+oltdLQN5cgC92hElwOWtK24AUu+cwwY9zTdf/O/iAf3c+/fVvAP0Re2O1YF4WLCKd57XpQYfFldc4lF1P2y9mwDt7ngxBnkTCivKCy9efWuHZ0ub5mWrebst9ZZBFS3B1kMZQH6cxplK4IwQBUhl2gp7yz4k=","uniqueId":1}}]}, CfDJ8AZe+klKAG9FitXUnFgRJ3vRx6CLYzNV9Mpxn+sV5Pk4nwkrwSyrNwxHdjchdfUqdFl2gi7nO6q9cwwOXTrVQOew2XC4s6tY8aQY4es/enhFDv4e9xFmvoFzaWsUCcikqZp4VuXFRa4p2rofjUq+2ehumxMWwsCeKza4ssNDmUtj2nKCu8l5I25QsoMtVtg4Zmuus9yZqPKhLDvcbvv2+0K4nmVFqx+Ueo6c9rLaurJcmUYHW31rWHLnwQV9jMD9eTLbTRph1sKxm7UJqYF3ZUsH6qFaaJ6xvSCO32OWabZ7RiN1Yr3kk+D6jPrLI+LkO+dK3eLYvRQO8Sfw8Rnq8vuEMUai09D1snnA+dBVeF8w6iAda6pQ4osiSfBCGP1QAOiGgieeHMuE2VPVgqwvXJn17pq7o4MrBqts6vZ835vMkfRqMpQS9LvQfDkmKObu0kIV5IOrWMsP+gUp4iTpLToEYwNS6PGzI86tvjUdl2Oy1hre0jmisACZATrCTVirdpzPdI//JWukmxnGiM8Qc/4PwfkIRhwRes60fhFpgftlSmGVl4acJZuDAvqaDQl/vZdT7uXaCfm6NIp3qT9+oBbjv31Fb4xdANwxCwSyiTvU ], StreamIds: [  ] }.
2025-08-25 10:48:01.373 +02:00 [DBG] Received hub invocation: InvocationMessage { InvocationId: "", Target: "OnRenderCompleted", Arguments: [ 2,  ], StreamIds: [  ] }.
2025-08-25 10:48:01.376 +02:00 [DBG] Received hub invocation: InvocationMessage { InvocationId: "", Target: "OnRenderCompleted", Arguments: [ 3,  ], StreamIds: [  ] }.
2025-08-25 10:48:01.378 +02:00 [DBG] Received hub invocation: InvocationMessage { InvocationId: "", Target: "EndInvokeJSFromDotNet", Arguments: [ 3, True, [3,true,null] ], StreamIds: [  ] }.
2025-08-25 10:48:01.383 +02:00 [DBG] Received hub invocation: InvocationMessage { InvocationId: "", Target: "EndInvokeJSFromDotNet", Arguments: [ 4, True, [4,true,null] ], StreamIds: [  ] }.
2025-08-25 10:48:01.401 +02:00 [DBG] Received hub invocation: InvocationMessage { InvocationId: "", Target: "EndInvokeJSFromDotNet", Arguments: [ 5, True, [5,true,null] ], StreamIds: [  ] }.
2025-08-25 10:48:01.425 +02:00 [DBG] Received hub invocation: InvocationMessage { InvocationId: "", Target: "OnRenderCompleted", Arguments: [ 4,  ], StreamIds: [  ] }.
2025-08-25 10:48:01.463 +02:00 [WRN] Unhandled exception rendering component: Response status code does not indicate success: 401 (Unauthorized).
System.Net.Http.HttpRequestException: Response status code does not indicate success: 401 (Unauthorized).
   at System.Net.Http.HttpResponseMessage.EnsureSuccessStatusCode()
   at Microsoft.AspNetCore.Http.Connections.Client.HttpConnection.NegotiateAsync(Uri url, HttpClient httpClient, ILogger logger, CancellationToken cancellationToken)
   at Microsoft.AspNetCore.Http.Connections.Client.HttpConnection.GetNegotiationResponseAsync(Uri uri, CancellationToken cancellationToken)
   at Microsoft.AspNetCore.Http.Connections.Client.HttpConnection.SelectAndStartTransport(TransferFormat transferFormat, CancellationToken cancellationToken)
   at Microsoft.AspNetCore.Http.Connections.Client.HttpConnection.StartAsyncCore(TransferFormat transferFormat, CancellationToken cancellationToken)
   at Microsoft.AspNetCore.Http.Connections.Client.HttpConnection.StartAsync(TransferFormat transferFormat, CancellationToken cancellationToken)
   at Microsoft.AspNetCore.Http.Connections.Client.HttpConnectionFactory.ConnectAsync(EndPoint endPoint, CancellationToken cancellationToken)
   at Microsoft.AspNetCore.Http.Connections.Client.HttpConnectionFactory.ConnectAsync(EndPoint endPoint, CancellationToken cancellationToken)
   at Microsoft.AspNetCore.SignalR.Client.HubConnection.StartAsyncCore(CancellationToken cancellationToken)
   at Microsoft.AspNetCore.SignalR.Client.HubConnection.StartAsyncInner(CancellationToken cancellationToken)
   at Microsoft.AspNetCore.SignalR.Client.HubConnection.StartAsync(CancellationToken cancellationToken)
   at BlazorApp6.Components.Pages.Home.<OnInitializedAsync>b__6_0() in C:\Users\USER123456\source\repos\akaioda\BlazorApp6\Components\Pages\Home.razor:line 126
   at BlazorApp6.Components.Pages.Home.OnInitializedAsync() in C:\Users\USER123456\source\repos\akaioda\BlazorApp6\Components\Pages\Home.razor:line 78
   at Microsoft.AspNetCore.Components.ComponentBase.RunInitAndSetParametersAsync()
   at Microsoft.AspNetCore.Components.RenderTree.Renderer.GetErrorHandledTask(Task taskToHandle, ComponentState owningComponentState)
2025-08-25 10:48:01.504 +02:00 [ERR] Unhandled exception in circuit 'bmXnhrXXSwBWyPMAKAx-abGGh9oduSMiq-uD5Vf634I'.
System.Net.Http.HttpRequestException: Response status code does not indicate success: 401 (Unauthorized).
   at System.Net.Http.HttpResponseMessage.EnsureSuccessStatusCode()
   at Microsoft.AspNetCore.Http.Connections.Client.HttpConnection.NegotiateAsync(Uri url, HttpClient httpClient, ILogger logger, CancellationToken cancellationToken)
   at Microsoft.AspNetCore.Http.Connections.Client.HttpConnection.GetNegotiationResponseAsync(Uri uri, CancellationToken cancellationToken)
   at Microsoft.AspNetCore.Http.Connections.Client.HttpConnection.SelectAndStartTransport(TransferFormat transferFormat, CancellationToken cancellationToken)
   at Microsoft.AspNetCore.Http.Connections.Client.HttpConnection.StartAsyncCore(TransferFormat transferFormat, CancellationToken cancellationToken)
   at Microsoft.AspNetCore.Http.Connections.Client.HttpConnection.StartAsync(TransferFormat transferFormat, CancellationToken cancellationToken)
   at Microsoft.AspNetCore.Http.Connections.Client.HttpConnectionFactory.ConnectAsync(EndPoint endPoint, CancellationToken cancellationToken)
   at Microsoft.AspNetCore.Http.Connections.Client.HttpConnectionFactory.ConnectAsync(EndPoint endPoint, CancellationToken cancellationToken)
   at Microsoft.AspNetCore.SignalR.Client.HubConnection.StartAsyncCore(CancellationToken cancellationToken)
   at Microsoft.AspNetCore.SignalR.Client.HubConnection.StartAsyncInner(CancellationToken cancellationToken)
   at Microsoft.AspNetCore.SignalR.Client.HubConnection.StartAsync(CancellationToken cancellationToken)
   at BlazorApp6.Components.Pages.Home.<OnInitializedAsync>b__6_0() in C:\Users\USER123456\source\repos\akaioda\BlazorApp6\Components\Pages\Home.razor:line 126
   at BlazorApp6.Components.Pages.Home.OnInitializedAsync() in C:\Users\USER123456\source\repos\akaioda\BlazorApp6\Components\Pages\Home.razor:line 78
   at Microsoft.AspNetCore.Components.ComponentBase.RunInitAndSetParametersAsync()
   at Microsoft.AspNetCore.Components.RenderTree.Renderer.GetErrorHandledTask(Task taskToHandle, ComponentState owningComponentState)
2025-08-25 10:48:01.511 +02:00 [DBG] OnConnectedAsync ending.
2025-08-25 10:48:01.512 +02:00 [DBG] Waiting for the application to finish sending data.
2025-08-25 10:48:01.512 +02:00 [DBG] Socket closed.
2025-08-25 10:48:01.513 +02:00 [DBG] Removing connection Zcwgu6iTkFOBbFhjzBnlBg from the list of connections.
2025-08-25 10:48:01.514 +02:00 [INF] Executed endpoint 'Microsoft.AspNetCore.Routing.RouteEndpoint'
2025-08-25 10:48:01.515 +02:00 [INF] Request finished HTTP/1.1 GET http://myhost.mydomain.com/_blazor?id=Zcwgu6iTkFOBbFhjzBnlBg - 101 null null 390.959ms
2025-08-25 10:48:12.683 +02:00 [INF] Request starting HTTP/1.1 POST http://myhost.mydomain.com/_blazor/disconnect - multipart/form-data; boundary=----WebKitFormBoundaryxRVRIRPt4GJerZI1 359
2025-08-25 10:48:12.683 +02:00 [INF] Executing endpoint 'Microsoft.AspNetCore.Routing.RouteEndpoint'
2025-08-25 10:48:12.691 +02:00 [INF] Executed endpoint 'Microsoft.AspNetCore.Routing.RouteEndpoint'
2025-08-25 10:48:12.691 +02:00 [INF] Request finished HTTP/1.1 POST http://myhost.mydomain.com/_blazor/disconnect - 200 null null 8.6101ms
2025-08-25 10:51:04.023 +02:00 [INF] Application is shutting down...

akaioda avatar Aug 25 '25 10:08 akaioda

@akaioda thanks for contacting us.

Does your code work on an app with SignalR app that doesn't involve Blazor?

That is, a signalr app with a SignalR Hub where you are using the HubClient in the same way you are right now.

javiercn avatar Aug 25 '25 13:08 javiercn

Hi @javiercn, thnaks for your attention !

I haven't tested this case because the core of the actual application (not the minimal example attached to report the issue) is built with Blazor...

akaioda avatar Aug 25 '25 14:08 akaioda

Hi @javiercn, thnaks for your attention !

I haven't tested this case because the core of the actual application (not the minimal example attached to report the issue) is built with Blazor...

The reason that I ask is because there shouldn't be anything Blazor specific to this, AFAIK.

Blazor runs inside a SignalR hub and as long as that work, we should be no different, if it doesn't work I'm not sure if this requires additional signalr config.

The other question/thing to account for is making sure that what you are trying to do makes sense. Hubconnection.StartAsync() runs as part of the server, not in the browser. If you are trying to do a loopback connection, that might be problematic and might not be what you are looking for.

javiercn avatar Aug 25 '25 15:08 javiercn

The ultimate goal is to be able to notify all open views of a change and respond to it or not ;-). To do this, the idea was to integrate a connection to the hub into MainLayout.razor and be able to receive hidden notifications, typically changes in rights, with immediate consideration. For example, the visibility of a control in the UI. To do this, we customize the claims, and the message received forces clients to reread them. So far, this works without any problems with IIS Express in VS 2022.

akaioda avatar Aug 25 '25 15:08 akaioda

@akaioda thanks for the additional details.

All the open views for a given browser/customer?

If this is for a single user/browser that has multiple opened windows/tabs, you could consider using https://developer.mozilla.org/en-US/docs/Web/API/MessageChannel for communicating across tabs

javiercn avatar Aug 25 '25 15:08 javiercn

@javiercn , no, communication must be possible with any client (user) using the Blazor application. The hub is designed to be configured to listen in the MainLayout.razor file, so that any tab opened to the application, regardless of the browser, will receive the notification and the user interface can respond accordingly. These are the basics, which have been implemented.

akaioda avatar Aug 25 '25 21:08 akaioda

@BrennanConroy are there docs on how to make this work with SignalR?

I don't think there's anything Blazor specific here.

javiercn avatar Aug 26 '25 09:08 javiercn

I don't think there's anything Blazor specific here.

@javiercn That is also my opinion, thank you for pointing that out. πŸ‘

akaioda avatar Aug 26 '25 11:08 akaioda

Your app works for me in IIS Express and IIS. That implies an environment specific issue.

The Windows 2019 server is in a network zone that is accessed through a load balancer that provides SSL termination and carries the certificates.

Does that mean when the HubConnection code in the Blazor Component runs it's hitting the load balancer? If it doesn't hit the load balancer with SSL does that cause problems? If you remove the load balancer for testing does the scenario work?

BrennanConroy avatar Aug 26 '25 18:08 BrennanConroy

Hi, @BrennanConroy We are in this configuration!

Image

Your app works for me in IIS Express and IIS. That implies an environment specific issue.

πŸ‘I agree

Does that mean when the HubConnection code in the Blazor Component runs it's hitting the load balancer?

yes

If you remove the load balancer for testing does the scenario work?

I can't in my context πŸ™„

If I'm not mistaken, in this connection phase, the server initiates a request to itself, and name resolution involves going through the LB. I tried to keep it internal by defining an entry in the server's Hosts file to keep it within the server's security domain. That also failed, but not in the same way, which gave me a clue about the target URL.

System.Net.Http.HttpRequestException: No connection could be established because the target machine actively refused it. (myhost.mydomain.com:443)
 ---> System.Net.Sockets.SocketException (10061): No connection could be established because the target machine actively refused it.
   at System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.ThrowException(SocketError error, CancellationToken cancellationToken)
   at System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.System.Threading.Tasks.Sources.IValueTaskSource.GetResult(Int16 token)...

Is it possible to configure the request, host name, and port/protocol differently? Would that be a possible solution? Is there any chance of finding a workable solution with this network architecture?

regards

akaioda avatar Aug 27 '25 14:08 akaioda

Is it possible to configure the request, host name, and port/protocol differently?

Sure, you can build the URI yourself using UriBuilder. e.g. new UriBuilder(Navigation.ToAbsoluteUri("/chathub")) { Scheme = "http", Port = 80 }.ToString()

Is there any chance of finding a workable solution with this network architecture?

Probably, but since it's likely some configuration in your load balancer that needs updating, we can't really help much.

BrennanConroy avatar Aug 27 '25 17:08 BrennanConroy

Hey, finally a result!

@BrennanConroy The test application related to this issue now works for me too in both environments with two modifications.

I configured the URI customization this way to address the case in development with IIS Express, and the case in β€œproduction” on the target IIS server:

#if DEBUG
                // using IIS express here
                hubConnection = new HubConnectionBuilder()
                    .WithUrl(Navigation.ToAbsoluteUri("/chathub"),               
                    config =>
                    {
                        config.UseDefaultCredentials = true;
                    })
                    .WithAutomaticReconnect()
                .Build();  
#else           
                // using IIS in a production environment release build
                var hostName = Environment.MachineName;
                var addresses = Dns.GetHostAddresses(hostName);
                var ipv4 = addresses.FirstOrDefault(addresses => addresses.AddressFamily == AddressFamily.InterNetwork)?.ToString();
                var uriBuilded = new UriBuilder(Navigation.ToAbsoluteUri("/chathub")) { Scheme = "http", Port = 80, Host=ipv4}.ToString();
                Log.LogInformation("chathub URI builded [{uriBuilded}]", uriBuilded);
                hubConnection = new HubConnectionBuilder()
                    .WithUrl(Navigation.ToAbsoluteUri(uriBuilded),
                    config =>
                    {
                        config.UseDefaultCredentials = true;
                    })
                    .WithAutomaticReconnect()
                .Build();
#endif

And I had to modify the bindings in the IIS configuration as follows by adding the line circled in green:

Image

However, no URI configuration for the host name, other than using the actual IP address of the server, seems to work. I haven't figured out why yet, so if anyone has an explanation, I'm all ears πŸ˜‰

In the meantime, I also explored a solution based on JavaScript functions with JS Interop, which allowed me to work around the problem using a different approach.

Ultimately, I'm not going to use this method, which involves integrating the SignalR javascript package on the client side, and requires partial exposure of javascript methods with message processing logic, necessary for interoperability with the underlying code of razor components. IMHO, in my context, from the point of view of improving security, this method seems less appropriate!

regards

akaioda avatar Aug 28 '25 12:08 akaioda

Hello,

I think this thread can now be closed, but @BrennanConroy, perhaps it would be a good idea for the aspnetcore/SignalR team to add some official implementation guidelines to the documentation for those who have a similar network configuration, which I believe must be quite common!

Best regards

akaioda avatar Sep 10 '25 10:09 akaioda

Moving to the docs repo, as it looks like a docs update is the action to consider here.

MackinnonBuck avatar Sep 17 '25 17:09 MackinnonBuck

πŸ–οΈπŸŒž Summertime!! Woot!! πŸβ›΅

Stand-by! ... A green dinosaur πŸ¦– will be along shortly to assist.

github-actions[bot] avatar Sep 17 '25 17:09 github-actions[bot]

We have an article for various proxy/load balancer scenarios at ...

https://learn.microsoft.com/en-us/aspnet/core/host-and-deploy/proxy-load-balancer

We have a SignalR hosting and scaling article at ...

https://learn.microsoft.com/en-us/aspnet/core/signalr/scale

There's the SignalR configuration article ...

https://learn.microsoft.com/en-us/aspnet/core/signalr/configuration

@danroth27 ... Do you want this covered at all? If so, where would you like the guidance placed?

guardrex avatar Oct 06 '25 13:10 guardrex

@mikekistler @BrennanConroy What are your thoughts on where this documentation should go?

danroth27 avatar Oct 23 '25 05:10 danroth27