0

I am working on an application to perform context synchronization between multiple web hosted applications using SignalR. The client machine instantiates a host using the SignalR Owin host and the applications connect to it with a no-proxy version of the JS Client. The issue I am having is that the "Client" applications are hosted in SSL environments the SignalR host is not (as it is constrained to the local machine). If I try to connect to the Hub from a standard non-SSL website hosting the javascript client everything works. As soon as I load the client into an SSL website however I get a "SignalR: Error during negotiation request: undefined" when I try to start the connection. Anyone know a way around this?

Host:

    public class SignalRHost : IDisposable
{
    private IDisposable _webApp;

    public SignalRHost(string url = "http://localhost:9000/")
    {
        _webApp = WebApplication.Start<Startup>(url);
    }

    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            bool enableErrorDetail = false;
#if DEBUG
            enableErrorDetail = true;
#endif
            app.MapHubs(new HubConfiguration { EnableCrossDomain = true, EnableDetailedErrors = enableErrorDetail });
        }

    }


    public void Dispose()
    {
        _webApp.Dispose();
    }
}

JS Client:

    (function (ns_HubClient) {
    ns_HubClient.connection;
    ns_HubClient.proxy;

    ns_HubClient.initialize = function () {
        ns_HubClient.connection = $.hubConnection("http://localhost:9000");
        ns_HubClient.proxy = ns_HubClient.connection.createHubProxy("fluencyHub");

        ns_HubClient.proxy.on('addMessage', function (data) { ns_HubClient.processMessage(data); });


        ns_HubClient.connection.start()
            .done(function () {
                alert("connection complete");
            })
            .fail(function (data) {
                alert("connection start failed: " + data);
            });
    };

    ns_HubClient.login = function (sUserName, sPassword, sDomain) {
        var fluencyMessage = {
            MessageId: "",
            CallType: "Asynchronous",
            Method: "Login",
            Status: "",
            Response: {},
            Request: {
                sUserName: sUserName,
                sPassword: sPassword,
                sDomain: sDomain
            }
        };

        ns_HubClient.sendMessage(fluencyMessage);
    };

    ns_HubClient.writeLog = function (message, errorLevel) {
        var logMessage = {
            ErrorLevel: errorLevel,
            Message: message
        };
        ns_HubClient.proxy.invoke("logMessage", logMessage);
    };

    ns_HubClient.processMessage = function (message) {

    };

    ns_HubClient.sendMessage = function (data) {
        ns_HubClient.proxy.invoke("addMessage", data);
    };

} (window.ns_HubClient = window.ns_HubClient || {}));
JMorgan
  • 805
  • 4
  • 11
  • 24

1 Answers1

2

The SignalR JS client makes an XHR to "negotiate" which transports (e.g. WebSockets) should be used to establish bidirectional communication with the SignalR server among other things.

Browser vendors can choose not to allow XHRs to be made from HTTPS pages to HTTP resources: http://www.w3.org/TR/access-control/#user-agent-security

Note the fourth bullet point: "user agents are allowed to terminate the algorithm and not make a request This could be done because e.g.: ... . https to http is not allowed."

A browser vendor might choose to do this since non-secure XHRs can make otherwise secure web applications vulnerable to man-in-the-middle attacks.

I would use your browser's F12 tools or use an HTTP proxy like fidler to verify the browser is actually making a "negotiate" request. If it is, you can look at the response to help figure out what's going in.

halter73
  • 15,059
  • 3
  • 49
  • 60