14

I'm making an application that involves a website on localhost as a user interface with Asp.net Core and SignalR Core.

My problem is that I get an authentication exception when starting the connection. I know this happens because I haven't ran dotnet dev-certs https --trust. But I can't expect an average user to run this command or have the dotnet SDK installed at all.

I've tried using

ServicePointManager.ServerCertificateValidationCallback += (sender, certificate, chain, sslPolicyErrors) => true;

in my Startup.cs (and other places, but I understand that it's a global setting. in any case it was executed before the HubConnection) to no avail. I also tried setting a new HttpMessageHandlerFactory, but the documentation tells me that doesnt affect Websockets.

I don't believe this is a solution, because I can't use a different HttpClient (unless I'm mistaken)

As you can see, I'm not connecting to https at all:

connection = new HubConnectionBuilder().WithUrl("http://localhost:5000/MiniLyokoHub" ).Build();

So I don't see why it is even trying to get the certificate.

Here is the full error: https://pastebin.com/1ELbeWtc

How can I get around this issue? I don't need a certificate, since the user will be connecting to their own localhost. Or should I just not use websockets?

GoodOldJack12
  • 305
  • 1
  • 2
  • 8
  • You are neither supposed to run websites locally in production, nor to use the dev cert on client machines. – Marco Mar 25 '19 at 19:30
  • Just a question: if the user is connecting always to localhost, why https at all? Wouldnt plain http suffice? – ZorgoZ Mar 25 '19 at 19:30
  • Possible duplicate of [bypass invalid SSL certificate in .net core](https://stackoverflow.com/questions/38138952/bypass-invalid-ssl-certificate-in-net-core) – Manoj Choudhari Mar 25 '19 at 19:33
  • @ZorgoZ it would suffice, and I'm connecting to the http port, but it still throws an exception – GoodOldJack12 Mar 25 '19 at 19:33
  • 1
    That's strange. Remember: secure SignalR will first try to use WSS instead of WS, not https or http. Check developer console for the actual protocol. – ZorgoZ Mar 25 '19 at 19:49
  • @ZorgoZ Where can I find the protocol? edited the post with some more information – GoodOldJack12 Mar 25 '19 at 20:00

3 Answers3

32

When connecting to HTTPS, to always recognise the SSL certificate as successfully verified in the SignalR Core client you should do this in HttpMessageHandlerFactory configs. Use HttpConnectionOptions in WithUrl method like this:

connection = new HubConnectionBuilder()
.WithUrl("https://localhost:443/MiniLyokoHub", (opts) =>
{
    opts.HttpMessageHandlerFactory = (message) =>
    {
        if (message is HttpClientHandler clientHandler)
            // always verify the SSL certificate
            clientHandler.ServerCertificateCustomValidationCallback +=
                (sender, certificate, chain, sslPolicyErrors) => { return true; };
        return message;
    };
})
.Build();
Chris Halcrow
  • 28,994
  • 18
  • 176
  • 206
Mahdi Ataollahi
  • 4,544
  • 4
  • 30
  • 38
  • Thank you so much! Exactly what I as someone who is using HTTPS was looking for! – The-IT Apr 10 '21 at 08:46
  • I tried many other approaches and this was the only one that worked. This works as a workaround if you're running a .NET Core app (that has a SignalR hub) in Docker using Linux containers. In my case, I successfully set up my .NET Core app that creates the SignalR hub, so that the app used https using the .NET Core self-signed developer certificate, but for some reason when the SignalR hub is running a Linux Docker container, any client connection to the SignalR hub was giving the error `The remote certificate is invalid according to the validation procedure`. – Chris Halcrow May 10 '21 at 03:36
  • Was having some trouble getting a Xamarin.Forms app to connect to a blazor hub hosted locally and this helped – Jay Sidri Jun 26 '22 at 00:38
  • It looks like this solution is helping a lot of people, so I'm going to mark it as the accepted solution. – GoodOldJack12 Jun 30 '22 at 07:15
  • This is incomplete. You also need to set `opts.WebSocketConfiguration = wsc => wsc.RemoteCertificateValidationCallback = (sender, certificate, chain, policyErrors) => true;`, else the websocket will fail and you'll get a "server disconnected before ... somthing" error. – JHBonarius Jun 06 '23 at 14:32
4

It seems that the SignalR Core Client is also subject to Https redirection Which is why it wouldn't connect to the http port.

For my use case, I just had to disable it in Startup.cs

GoodOldJack12
  • 305
  • 1
  • 2
  • 8
  • how did you disable that? – pregmatch Jun 28 '22 at 19:45
  • 1
    @pregmatch it's been forever but I believe you're looking for `app.UseHttpsRedirection();`. If you remove that line, it wont redirect https. That being said it looks like the top voted answer might help you better – GoodOldJack12 Jun 30 '22 at 07:13
0

When connecting using HTTPS, to always recognise the SSL certificate as successfully verified in the SignalR Core client, you need to add the following so that it is verified for both http and wss:

var connection = new HubConnectionBuilder()
    .WithUrl("https://localhost:443/MiniLyokoHub", (opts) =>
    {
        opts.HttpMessageHandlerFactory = (message) =>
        {
            if (message is HttpClientHandler clientHandler)
                // always verify the SSL certificate
                clientHandler.ServerCertificateCustomValidationCallback +=
                (sender, certificate, chain, sslPolicyErrors) => { return true; };
            return message;
        };
        options.WebSocketConfiguration = wsc => wsc.RemoteCertificateValidationCallback = (sender, certificate, chain, policyErrors) => true;
    })
    .Build();
Chris Halcrow
  • 28,994
  • 18
  • 176
  • 206