I am trying to inject IPrincipal
into my SignalR hub constructors.
I already saw and tried the solution from "Selective IPrincipal Injection via StructureMap with SignalR", but unfortunately that doesn't seem to work anymore for SignalR 2.x.
In my debugging, I've discovered that sometimes, my hub constructor is called with my OWIN middleware in the stack. When that is the case, Thread.CurrentPrincipal
is the correct value. Additionally (and surprisingly), HttpContext.Current
is also not-null. I was under the impression this was always null in SignalR, and I'm not attempting to use it, but I'm just observing. It seems like these calls that do work come from the pipeline in the call stack.
Other times, calls seem to come from the thread pool. In those instances, Thread.CurrentPrincipal
is a GenericPrincipal
, HttpContext.Current
is null (again just observing), and I cannot seem to get at the principal statically. However, inside the hub, the this.Context.User
property does have the right principal.
How else can I get the principal statically so that I can inject it into the hub constructor?
It is expected that HttpContext.Current
and Thread.CurrentPrincipal
will sometimes be set when SignalR Hubs get activated, but not always. This is because the activating thread often runs with ASP.NET's SynchronizationContext
. There are situations when this isn't the case, such as when a Hub is activated in order to handle a WebSocket message or an unclean OnDisconnected event. Long story short, sometimes these statics happen to be there, but you cannot rely on it.
I don't know of any way to statically get the IPrincipal
reliably. What's wrong with using Context.User
inside your Hub?
If I understood correctly what you're trying to do... You should build your own Authorize attribute, that will put the custom principal into a special Owin var, then it will be accessible in Context.User
inside a hub.
public class MyAuthorizeAttribute : AuthorizeAttribute
{
public override bool AuthorizeHubConnection(HubDescriptor hubDescriptor, IRequest request)
{
//put our custom user-principal into a magic "server.User" Owin variable
request.Environment["server.User"] = new MyCustomPrincipal(); //<!-THIS!
return base.AuthorizeHubConnection(hubDescriptor, request);
}
}
And then apply this attribute to your Hub.
If you want more info on this, I blogged about this here with more code samples
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