This question is related to another thread, you can read here: Forms authentication with SignalR where I tried with the help and patience of the user dfowler to understand how enforce forms ASP .NET Forms Authentication on a SignalR Hub.
Description of the problem: I want that only authenticated users can connect the SignalR Hub and receive/send messages.
Intrusion scenario: the intruder can potentially capture/access the HTML and Javascripts of the web page accessing the temporary files on a client computer. This intruder can therefore know all the details (methods, hub names etc) required to set up/use a connection to the Hub. A proposed solution from dfowler is implementing IConnect:
You would implement IConnected and write the following code in Connect if(!Context.User.Identity.IsAuthenticated) throw new Exception("GTFO");
Therefore I tried with something like this
public System.Threading.Tasks.Task Connect()
{
if (!Context.User.Identity.IsAuthenticated
|| !(Context.User.IsInRole("role1") || Context.User.IsInRole("role2")
))
throw new Exception("User not authorized");
return null;
}
The problem, once tested, is that when the Connect method is being called, the connection has been already established and plain throwing the exception will not help (if I got if properly infact Connect should be used to send a message to the client at connection, throwing an exception will just yield in a welcome message not sent).
In facts, from my tests, the clients can still read all the messages (and also send them).
Now, approaches which come to my mind:
Any other approach? Any way to terminate the connection on server side or should be accepted that the only real authentication is the one of the host webpage (leaving open the door to all the signalR client attacks?)
EDIT
Here is the sequence of client - server communication when I use the IConnect.Connect
method throwing unconditionally an exception (browser IE9):
It looks like the foreverFrame fails but the longPolling fallback is being established and works anyway - this after throwing the error captured in the Javascript by the block
if (connection.state === signalR.connectionState.connecting) {
// Connection hasn't been started yet
throw "SignalR: Connection has not been fully initialized.
Use .start().done() or .start().fail() to run logic after
the connection has started.";
}
In a browser-based app, cookie authentication allows your existing user credentials to automatically flow to SignalR connections. When using the browser client, no additional configuration is needed. If the user is logged in to your app, the SignalR connection automatically inherits this authentication.
IIS on client operating systems has a limit of 10 concurrent connections. SignalR's connections are: Transient and frequently re-established. Not disposed immediately when no longer used.
A SignalR connection can end in any of the following ways: If the client calls the Stop method, a stop message is sent to the server, and both client and server end the SignalR connection immediately.
ConnectionTimeout = TimeSpan. FromSeconds(40); // Wait a maximum of 30 seconds after a transport connection is lost // before raising the Disconnected event to terminate the SignalR connection. GlobalHost. Configuration.
We have an issue where we need to allow blocking the connection altogether. Right now you'll have to guard each method. It's not the cleanest but for 1.0 alpha1 we'll have some mechanism for doing this.
One additional problem is that it's the same connection for all hubs so you can't reject a connection for a specific hub.
EDIT
Actually if you throw it does end the connection as far as my testing goes. What behavior are you seeing?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With