Is it possible to use HttpModule to authenticate for SignalR

Viewed 569

I am developing an application that uses an HttpModule to perform custom authentication and authorization. My problem is that the user Identity set in the HttpModule is not accessible in the SignalR context objects.

I do the following in my HttpModule BeginRequest handler after custom authentication logic:

var userClaims = new List<Claim>();
userClaims.Add(new Claim(ClaimTypes.NameIdentifier, <some id>));
userClaims.Add(new Claim(ClaimTypes.Name, <some name>));
userClaims.Add(new Claim(ClaimTypes.Email, <da email>));
userClaims.Add(new Claim(ClaimTypes.Authentication, "true"));

var id = new ClaimsIdentity(userClaims);
var principal = new ClaimsPrincipal(new[] { id });
Thread.CurrentPrincipal = principal;
HttpContext.Current.User = principal;

I thought that this would absolutely make everything hereafter behave as though the request was authenticated, however this is not the case.

I have created a SignalR AuthorizeAttribute class to handle the authentication that looks like this:

[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
public class CustomAuthAttribute : AuthorizeAttribute
{
    public override bool AuthorizeHubConnection(HubDescriptor hubDescriptor, IRequest request)
    {
        if (HttpContext.Current.Request.Path.StartsWith("/signalr/connect"))
        {
            var test = (ClaimsPrincipal)HttpContext.Current.User;
            var test2 = (ClaimsPrincipal)Thread.Current.Principal;
        }

        return true;
    }

    public override bool AuthorizeHubMethodInvocation(IHubIncomingInvokerContext hubContext, bool appliesToMethod)
    {
        var test = (ClaimsPrincipal)hubContext.Hub.Context.User;
        return true;
    }
}

So my plan was to access the hubContext.Hub.Context.User var from within the AuthorizeHubMethodInvocation method to do any custom authorization I needed. However this just contains the default WindowsPrincipal.

If I look into the AuthorizeHubConnection call (which is actually a regular HTTP request and not a websocket call), I see that the HttpContext.Current object also does not have the User set as it should.

I do see that I can access the HttpContext.Current.Items collection. I presume I could use this to toss the Principal from the module to the SignalR context, but I'm not sure that is what I'm supposed to do.

Is it best to simply rewrite the HttpModule as OWIN middleware? It looks like I'll have to change stuff anyways when/if we update to ASP.NET 5; there's nothing like MS products to give you job security.

1 Answers
Related