Search code examples
asp.net-mvcasp.net-mvc-5signalrauthorizeself-hosting

Context.User is null in self-hosted SignalR hub when called from IIS-hosted MVC app


I'm have an IIS hosted MVC 5 app that uses Asp.Net Identity and OWIN for authentication via .AspNet.ApplicationCookie. From one of its views, I make calls to long-running methods on a self-hosted SignalR hub (running on the same server) via a SignalR JS client. These calls all work as expected. I now wish to decorate my hub with [Authorize(Roles = "Administrator")]. This has proved problematic. Setting a breakpoint in a hub method reveals that the Context.User is null, even though the .AspNet.ApplicationCookie is clearly in the Context.RequestCookies.

Here is the bootstrap for the hub (self-hosted in a windows service):

app.Map("/signalr", map =>
{
    map.UseCors(CorsOptions.AllowAll);
    map.UseCookieAuthentication(new CookieAuthenticationOptions
    {
        AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie
    });

    var hubConfiguration = new HubConfiguration();
    map.RunSignalR(hubConfiguration);
});

Here is the auth config for the web app (hosted in IIS):

// Configure the db context, user manager and signin manager to use a single instance per request
app.CreatePerOwinContext(UserAccountContext.Create);
app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
app.CreatePerOwinContext<ApplicationSignInManager>(ApplicationSignInManager.Create);

// Enable the application to use a cookie to store information for the signed in user
// and to use a cookie to temporarily store information about a user logging in with a third party login provider
// Configure the sign in cookie
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
    AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
    LoginPath = new PathString("/Account/Login"),
    Provider = new CookieAuthenticationProvider
    {
        // Enables the application to validate the security stamp when the user logs in.
        // This is a security feature which is used when you change a password or add an external login to your account.  
        OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, ApplicationUser>(
            validateInterval: TimeSpan.FromMinutes(30),
            regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager))
    }
});

Question 1: Is the use of [Authorize] possible in the scenario described above? If so, how?

Question 2: Would it be better to just merge the self-hosted hub into the IIS hosted app? If so, are there any issues with long-running hub methods under IIS?

Update 1 I've tried adding TicketDataFormat = new TicketDataFormat(new MachineKeyDataProtector("ASP.NET Identity")) to the CookieAuthenticationOptions on my hub config, but that didn't help. Sure seems like this should be easier than it is.


Solution

  • I ended up moving my self-hosted hub into my ASP.Net application and it worked just fine. This seemed easier and more maintainable than implementing the workaround in this SO question, OWIN Self-Host CookieAuthentication & Legacy .NET 4.0 Application / FormsAuthenticationTicket