Search code examples
c#asp.net-mvc-5signalriis-8impersonation

SignalR have MVC IIS client Impersonate Current Windows User


I'm in the middle of messing around with SignalR figuring out cool things to use it for in a currently deployed intranet MVC application. The current setup looks like this (already existing besides signalr):

Architecture: Windows User Browser --> Load balanced MVC web app --> SignalR host

With this architecture I'm trying to figure out if something I want to do with authentication is possible. What I would like to do is have the MVC application (which is currently running under a windows service account) impersonate the windows user that is currently logged in to the MVC application instead of connecting to the SignalR hub as itself. This way I can reuse my authentication I already built into the MVC app as well in case there are things I don't want certain users to invoke, or if I want to restrict certain SignalR actions to only allowing the MVC app running under the service account to execute.

I tried using the below example as pointed out in the SignalR documentation but it doesn't work server side (obviously) because the default credentials are the service account's credentials.

var hubConnection = new HubConnection(System.Configuration.ConfigurationManager.AppSettings["fwServiceAddress"].ToString());
            hubConnection.Credentials = CredentialCache.DefaultCredentials;
            IHubProxy customerHub = hubConnection.CreateHubProxy("customer");
            await hubConnection.Start();
            await customerHub.Invoke("NewNoteAdded", newNote);

When the SignalR hub is called the User is the service account instead of the actual windows user because of the different layers of the application. If there's no way to impersonate I'm sure I can get creative.


Solution

  • Based on Connection.Credentials Property and CredentialCache.DefaultCredentials Property.

    The DefaultCredentials property applies only to NTLM, negotiate, and Kerberos-based authentication. DefaultCredentials represents the system credentials for the current security context in which the application is running. For a client-side application, these are usually the Windows credentials (user name, password, and domain) of the user running the application. For ASP.NET applications, the default credentials are the user credentials of the logged-in user, or the user being impersonated.

    Assuming you are using a different form of authentication, you can create your credentials based on the current logged-in user. Take a look at ICredentials Interface.

    The code is tad bit too long, so just check it out. Implementing the ICredentials Interface contains only one method that returns NetworkCredential Class. Simply construct the NetworkCredentialClass instance using the current logged-in user's credentials.

    At the end, you'd have something like this:

    var hubConnection = new HubConnection(System.Configuration.ConfigurationManager.AppSettings["fwServiceAddress"].ToString());
    hubConnection.Credentials = CredentialCache.DefaultCredentials; // returns ICredentials
    IHubProxy customerHub = hubConnection.CreateHubProxy("customer");
    await hubConnection.Start();
    await customerHub.Invoke("NewNoteAdded", newNote);
    

    Please note by logged-in user I mean logged-in on your MVC application and not on the client computer. If you want the credentials of the active directory user then you must also implement windows authentication on your web app. See How to implement Windows authentication and authorization in ASP.NET.