Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Inject IPrincipal with SignalR

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?

like image 443
David Pfeffer Avatar asked Oct 19 '22 20:10

David Pfeffer


2 Answers

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?

like image 147
halter73 Avatar answered Oct 22 '22 09:10

halter73


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

like image 26
Alex from Jitbit Avatar answered Oct 22 '22 10:10

Alex from Jitbit