David Pfeffer
David Pfeffer

Reputation: 39871

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?

Upvotes: 6

Views: 1663

Answers (3)

Alex from Jitbit
Alex from Jitbit

Reputation: 60922

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

Upvotes: 2

Balu
Balu

Reputation: 33

I was trying to solve the same problem and I found solution to set the identity of the user.

My application is saml protected and client application sends "SAML" token as part of header. We have written Asp.net module to verify the token and prepare identity of the user and add value to the response Headers.

I have created OwinStartup class and I have added my own request processor by using below code. I have tested this piece of code for Longpolling and working fine. I am not sure how it works in "WebScoket".

 public void Configuration(IAppBuilder app)
    {
        // Any connection or hub wire up and configuration should go here           
        try
        {
            app.Use(SetMyPrincipalObject);
        }
    }

  private Task SetMyPrincipalObject(IOwinContext arg1, Func<Task> arg2)
    {
        //var p = "Process response";//Process Response Header here and //create identity
        //arg1.Request.User = p;
        //return arg2.Invoke();
    }

Upvotes: 0

halter73
halter73

Reputation: 15244

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?

Upvotes: 2

Related Questions