locked
Asp.Net MVC 5, how to impersonate user on IIS RRS feed

  • Question

  • User-1351912183 posted

    Hi

    We are having issues with user impersonation in the MVC 5 using windows authentication for the use of kerberos protocol to access remote resource (none .net web services).

    The platform that we are running is windows 2008 server and iis7.5 web server. It seems that if we use the MVC 5 framework to for our web application, the usual web.config configuration for impersonate user and delegate that user credential to external resource is not supported?

    If that is so, what is the alternitive method to let the application pool user impersonate and delegate the end users credential to external resource using the MVC 5 framework?

    Note: we are working in kerberized environment and thus the web application is kerberized also.

    Kind regards,

    Eirikur Ari

    Tuesday, January 14, 2014 6:04 AM

Answers

  • User1779161005 posted

    You can always impersonate in code:

    public void DoWorkWithClientCreds()
    {
      // grab client identity
      WindowsIdentity id =
        (WindowsIdentity)Context.User.Identity;
    
      // impersonation is automatically undone by
      // WindowsImpersonationContext.Dispose()
      using (WindowsImpersonationContext wic = id.Impersonate())
      {
        // access resource using client credentials 
        using (TextReader tr = File.OpenText("foo.txt"))
        { }
      }
    }
    

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Tuesday, January 14, 2014 8:29 AM
  • User-1454326058 posted

    Hi eirikur,

    Based on Brock’s reply or the link in my pervious reply. We can impersonate the Authenticating user in code.

    To impersonate a specific user for all the request, we can set the identity in the web.config. However, if we don’t want impersonate user for all request, we could impersonate the authentication user in code. (Windows authentication, we needn’t set the identity in the web.config, it will need us authentication during the runtime)

    Based on my test in VS2013 MVC5, it works fine. This is my test code below:

     public ActionResult Index()
            {
                string currentUser = System.Security.Principal.WindowsIdentity.GetCurrent().Name;
    
                System.Security.Principal.WindowsImpersonationContext impersonationContext;
                impersonationContext =
                    ((System.Security.Principal.WindowsIdentity)User.Identity).Impersonate();
    
                currentUser += "Impersonate:" + System.Security.Principal.WindowsIdentity.GetCurrent().Name;
    
    
                impersonationContext.Undo();
                ViewBag.U = currentUser;
                return View();
            }

    The result is:

    IIS APPPOOL\Net4Classic Impersonate:current logging user


    Thanks

    Best Regards  

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Wednesday, January 15, 2014 4:42 AM
  • User-474980206 posted

    eirikur.ari

    It is just so dirty surronding every call with windows impersonation context :)

    the issue with generic impersonation (old implementation), is that asp.net thread agiility made this difficult. in the old code, the identity was saved (with the request context), then assigned to the thread when pulled from the pool to do its part of the request. but adding in async support to asp.net makes this even more difficult.

    because a thread could be running another users request when the first users async event fires, this means all tasks need to be wrapped with code to save the current thread identity, switch to the desired identity  then restore on completion. without compiler changes this would mean a new async task classes would need to be defined and used instead of the standard task/await. as 1 async task can interupt another running async task, the bookkeeping gets even difficult.

    also as you don't want to give users more access than necessary, it makes sense to only impersonate around the call that need their token.

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Wednesday, January 15, 2014 11:08 AM

All replies

  • User-1351912183 posted

    Hi dev.paudel

    Thanks for the reply. Unfortunately this does not help. Because if <identity impersonate="true" /> is used with the MVC5 web application, the web server will complain about the impersonation. This of course works splendidly on the prior MVC frameworks, but it seems that it is not optional in MVC5 framework.

    So this does not help me.

    Kind regards,

    Eirikur Ari

    Tuesday, January 14, 2014 7:55 AM
  • User-1351912183 posted

    If i understand this correctly, then using anonymous authentication and windows authentication it will impersonate the end user. But the endpoint credential is still the application pool user but should be the end user (authenticated user).

    Any help is much appreciated.

    Kind regards,

    Eirikur Ari

    Tuesday, January 14, 2014 8:16 AM
  • User1779161005 posted

    You can always impersonate in code:

    public void DoWorkWithClientCreds()
    {
      // grab client identity
      WindowsIdentity id =
        (WindowsIdentity)Context.User.Identity;
    
      // impersonation is automatically undone by
      // WindowsImpersonationContext.Dispose()
      using (WindowsImpersonationContext wic = id.Impersonate())
      {
        // access resource using client credentials 
        using (TextReader tr = File.OpenText("foo.txt"))
        { }
      }
    }
    

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Tuesday, January 14, 2014 8:29 AM
  • User-1454326058 posted

    Hi eirikur,

    There is a link about impersonation in an ASP.NET application that may benefit you:

    # How to implement impersonation in an ASP.NET application

    http://support.microsoft.com/kb/306158/en-us

    Thanks

    Best Regards  

    Wednesday, January 15, 2014 1:16 AM
  • User-1351912183 posted

    Hi BrockAllen

    I thank you for your reply. This method is the other possibiltiy to impersonate user calling webservice. It seems that the asp .net impersonate support for iis (web.config) has been removed from the MVC 5 framework. So my question was if there was any other posibility of impersonate user in webservice call than surrontind the method win using statement that is callling WindowsIdentity in code.

    The other thing was realy convenient, just to insert <idendity impersonate="true" /> in the web.config.

    It is just so dirty surronding every call with windows impersonation context :)

    Kind regards

    Eirikur Ari

    Wednesday, January 15, 2014 2:19 AM
  • User-1351912183 posted

    Hi Starain,

    I thank you for your reply. It seems that the asp .net impersonate support for iis (web.config) has been removed from the MVC 5 framework. So my question was if there was any other posibility of impersonate user in webservice call than surrontind the method win using statement that is callling WindowsIdentity in code.

    The other thing was realy convenient, just to insert <idendity impersonate="true" /> in the web.config.

    It is just so dirty surronding every call with windows impersonation context :)

    Kind regards

    Eirikur Ari

    Wednesday, January 15, 2014 2:24 AM
  • User-1454326058 posted

    Hi eirikur,

    Based on Brock’s reply or the link in my pervious reply. We can impersonate the Authenticating user in code.

    To impersonate a specific user for all the request, we can set the identity in the web.config. However, if we don’t want impersonate user for all request, we could impersonate the authentication user in code. (Windows authentication, we needn’t set the identity in the web.config, it will need us authentication during the runtime)

    Based on my test in VS2013 MVC5, it works fine. This is my test code below:

     public ActionResult Index()
            {
                string currentUser = System.Security.Principal.WindowsIdentity.GetCurrent().Name;
    
                System.Security.Principal.WindowsImpersonationContext impersonationContext;
                impersonationContext =
                    ((System.Security.Principal.WindowsIdentity)User.Identity).Impersonate();
    
                currentUser += "Impersonate:" + System.Security.Principal.WindowsIdentity.GetCurrent().Name;
    
    
                impersonationContext.Undo();
                ViewBag.U = currentUser;
                return View();
            }

    The result is:

    IIS APPPOOL\Net4Classic Impersonate:current logging user


    Thanks

    Best Regards  

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Wednesday, January 15, 2014 4:42 AM
  • User-1351912183 posted

    Hi Starain,

    Yes this seems to be the options to impersonate the user. The code works also in the MVC5 so i assume the only change was in the iis config. So this is a valid answer. 

    So i thank you all for your reply's.

    Kind regards,

    Eirikur Ari

    Wednesday, January 15, 2014 11:06 AM
  • User-474980206 posted

    eirikur.ari

    It is just so dirty surronding every call with windows impersonation context :)

    the issue with generic impersonation (old implementation), is that asp.net thread agiility made this difficult. in the old code, the identity was saved (with the request context), then assigned to the thread when pulled from the pool to do its part of the request. but adding in async support to asp.net makes this even more difficult.

    because a thread could be running another users request when the first users async event fires, this means all tasks need to be wrapped with code to save the current thread identity, switch to the desired identity  then restore on completion. without compiler changes this would mean a new async task classes would need to be defined and used instead of the standard task/await. as 1 async task can interupt another running async task, the bookkeeping gets even difficult.

    also as you don't want to give users more access than necessary, it makes sense to only impersonate around the call that need their token.

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Wednesday, January 15, 2014 11:08 AM
  • User1779161005 posted

    Normally doing the impersonation where it's needed is best practice since you really should only need impersonation around the resource access.

    Wednesday, January 15, 2014 11:30 AM
  • User-1351912183 posted

    Hi Bruce,

    This is the answer that i was looking for.  Thank you, this makes a lot of sense.

    Kind regards,

    Eirikur Ari

    Wednesday, January 15, 2014 5:47 PM
  • User401360897 posted

    Just wanted to add something why the web.config impersonate not work and explicitly calling WindowsIdentity.Impersonate works. This is due to an optimization done in async/await in the framework.

    if the code invoking ThreadPool.QueueUserWorkItem was impersonating a Windows identity at the time, that same Windows identity would be impersonated in order to run the supplied WaitCallback delegate. And if the code invoking Task.Run had first stored data into the LogicalCallContext, that same data would be accessible through the LogicalCallContext within the supplied Action delegate. ExecutionContext is also flowed across awaits on tasks.

    There are multiple optimizations in place in the Framework to avoid capturing and running under a captured ExecutionContext when doing so is unnecessary, as doing so can be quite expensive. However, actions like impersonating a Windows identity or storing data into LogicalCallContext will thwart these optimizations. Avoiding operations that manipulate ExecutionContext, such as WindowsIdentity.Impersonate and CallContext.LogicalSetData, results in better performance when using asynchronous methods, and when using asynchrony in general.

    Details here,

    http://msdn.microsoft.com/en-us/magazine/hh456402.aspx

    Saturday, January 18, 2014 2:56 PM