I use SignalR 1.0.1 as a chat core for ASP.NET MVC3 application. Using IIS 7.5
There are two methods in MVC controller which provides access to chat views:
1. First method is public, allowing anonymous users to chat - no authorization.
2. Access to second method is restricted with [Authorize]
attribute, for domain users - chat agents.
There is no explicitly specified authorization in the Hub.
For this scenario I involved both Windows and Anonymous authentication on IIS.
I also implemented custom Role Provider, which operates only in memory - not persisting anything to database.
What happens is that using '[Authorize]' attribute in controller method leads to responsing 500 from Hub, both when call is coming from authorized view, and the anonymous one:
Request (send
is Hub method for sending messages):http://localhost:8101/signalr/send?transport=serverSentEvents&connectionToken=VIXEZzWQSn5SNlA8RUy4iaOPDFdvuPBjMvFBiG2FLfvfxF347XHwtapsEV5ndU4OEI0Xb64W2ZRXTqwBiL2CXg2_JlTaTJ2RnVOj4bjvx6tQaYhAqTaXs9k2853GYqzd0
Response:The connection id is in the incorrect format.
Server stack trace:
at Microsoft.AspNet.SignalR.PersistentConnection.GetConnectionId(HostContext context, String connectionToken)
at Microsoft.AspNet.SignalR.PersistentConnection.ProcessRequest(HostContext context)
at Microsoft.AspNet.SignalR.Owin.CallHandler.Invoke(IDictionary2 environment)
at Microsoft.AspNet.SignalR.Owin.Handlers.HubDispatcherHandler.Invoke(IDictionary2 environment)
at Microsoft.Owin.Host.SystemWeb.OwinCallContext.Execute()
at Microsoft.Owin.Host.SystemWeb.OwinHttpHandler.BeginProcessRequest(HttpContextBase httpContext, AsyncCallback callback, Object extraData)<br/><br/>
But notice, that connecting to Hub works fine, returns 200 OK:http://localhost:8101/signalr/connect?transport=serverSentEvents&connectionToken=dYOwFxa1mkgdpzw-jitRpWq9oxRlrTet8U_dAzWjFQEdGNJfVXeG7Op0NZZwvznxeNdJCuPT75CKzQqI9HRPThV3uEDt-Z2qtIl9E02gF481&connectionData=%5B%7B%22name%22%3A%22chathub%22%7D%5D&tid=9
I found little similiar thread here on stackoverflow:
signalr The connection id is in the incorrect format
from which I understand, that when invoking my Send
method, the Hub is processing request with Identity
different than the one used to connect to Hub, OR Hub's GetConnectionId
finds, that user is actually not authorized - but how it checks that assumption, when there is no authorization specified on the Hub itself?
Can someone put some light on this?
Thanks in advance :)
SignalR signs both your connection id and your Identity
together in order to create a new connectionToken
every time you start a new connection. This connectionToken
is then sent to the SignalR client as part of the negotiate
response.
Every time you make a request to SignalR, whether it be a connect
, reconnect
, or send
request, SignalR verifies that your connectionToken
matches both your client's connection id AND Identity
.
The connectionToken
is essentially a CSRF token used in order to prevent attackers running third-party websites from surreptitiously making SignalR requests on behalf of shared clients. Obviously this doesn't help if you've enabled SignalR's cross-domain support, but the connectionToken
still works the same in this case.
Taylor's answer was correct. You should stop
and then start
your SignalR connection when your client's Identity
changes. This will force a new negotiate
request which will give your client a new connection id with a new connectionToken
signed with your client's updated Identity
.
P.S. The server-sent events connect
request isn't failing because it was established before your client's Identity
was changed. The connectionToken
is only checked at the request is received, but server-sent events keeps the response open indefinitely.
That's all true what you said and it actually takes place in my issue.
But I also found the the root cause:
One of main assumptions during design was to allow both anonymous users to use the chat without need to sign-in and the back-end users (agents) to sign-in to restricted area of chat using their Windows credentials.
So on the IIS manager I enabled both Anonymous authentication (allowing anonymous users to use the chat) and the Windows authentication (allowing agents to access using their Windows credentials).
MVC application is configured to use Windows authentication - the [Authorize]
attribute mentioned in question, but only to restrict access for agent's view of chat.
What actually happens with above configuration is:
1. When client (agent) requests restricted View (let's say it's /Chat/Agent
) the [Authorize]
attribute initializes authentication (Windows)
2. Client-side Javascript requests Negotiate
, what generates connectionId
and binds it with client's Windows Identity
3. Here is the tricky part: Because Hub not uses any authentication explicitly, calling send
method does not result in any authentication request - IIS Anonymous authentication takes precedency before Windows authentication, and send
request is sent with anonymous Identity
- but in Hub actual connectionId
is related to Identity
passed in point 2.
This scenario leads to situation you described - connect
is called with different Identity
than send
and Hub returns The connection id is in the incorrect format.
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