SignalR - Send message to user using UserID Provider
I have not looked into SignalR 2.0 but I think this is an extension of what the previous versions of SignalR used to have. When you connect to the hub you can decorate it with an Authorize attribute
[HubName("myhub")]
[Authorize]
public class MyHub1 : Hub
{
public override System.Threading.Tasks.Task OnConnected()
{
var identity = Thread.CurrentPrincipal.Identity;
var request = Context.Request;
Clients.Client(Context.ConnectionId).sayhello("Hello " + identity.Name);
return base.OnConnected();
}
}
As you can see you are able to access the Identity of the user accessing the Hub. I believe the new capability would be nothing more than an extension of this. Since the connection is always kept alive between the client and the hub you will always have the principal identity which will give you the UserId.
Related videos on Youtube
hatcyl
Updated on September 15, 2022Comments
-
hatcyl over 1 year
Using SignalR, I believe I should be able to send messages to specific connected users by using UserID Provider
Does anyone have an example of how this would be implemented? I've searched and searched and can not find any examples. I would need to target a javascript client.
The use case is, users to my site will have an account. They may be logged in from multiple devices / browsers. When some event happens, I will want to send them a message.
-
hatcyl over 10 yearsUhm ... maybe I misunderstood their documentation. Before you could manually sync user ids to connection ids and broadcast appropriately.I thought the point of the UserID Provider was to eliminate this manual tracking. I though it would somehow know who the user was based on the the same User that the normal Authentication uses.
-
davidfowl over 10 yearsThe point is exactly that, if you have the user name, you don't have to track anything. By default it'll use the user name (if you're using some form of auth that sets the principal)
-
-
hatcyl over 10 yearsIn debugging my application, when connecting from my javascript client , both Thread.CurrentPrincipal.Identity and Context.Request are empty. Is there a special way to connect from javascript so that it knows it needs that info?
-
Gjohn over 10 yearsWell, how are you logging into your application? Do you have any piece that is doing the authentication?
-
hatcyl over 10 yearsI've been reading up on this. For my MVC and WebApis I have an HttpModule which does Basic Auth and sets the Principal from there. This is working well for the APIs and Views in MVC. However, I am reading that with the SignalR connections I think those Authorization headers do not get sent. So that may be the underlying issue I am facing.
-
Gjohn over 10 yearsThere should be no reason that your Hub would not be able to use that. Have you added the GlobalHost.HubPipeline.RequireAuthentication(); to your global.asax or wherever you have registered your hub?
-
hatcyl over 10 yearsJust tries. No go. Thanks though.
-
hatcyl over 10 yearsHave not tried, but will. However, I should not need to "require" it right? I should be able to have Authorized as well as Anonymous users?
-
Gjohn over 10 yearsNot if you added the GlobalHost.HubPipeline.RequireAuthentication(); that will force the users to be authenticated in which case anonymous uses won't be able to access your hub.
-
Gjohn over 10 yearsThat being said - you should be able to add your own custom authorization to handle anonymous users. You would just need to have a way of ensuring that those users would have a valid userId - even something that is temporarily created. see - asp.net/signalr/overview/signalr-20/security/hub-authorization
-
hatcyl over 10 yearsThanks, I'll try some of the suggestions and keep researching. I'll keep you guys posted.
-
hatcyl over 10 yearsI think I figured it out following your suggestions. The browser by default when connecting does not send Authorization Headers. Only once it receives the 401 error will it try again sending the Authorization. By adding the Authorized attribute to my Hub, the browser was forced to send the Authorization headers and now I am able to access Context.User correctly.
-
Gjohn over 10 years@hatcyl - glad I could help.
-
MemeDeveloper almost 10 yearsas dfowler says no need to do this : "To use this default implementation, first register it in GlobalHost when the application starts up:" as its the default.