ASP.Net Identity losing Impersonation

2.2k views Asked by At

I'm having a lot of problems that whenever I call an ASP.Net Identity Async method I get access denied exceptions from SQL server.

The following returns a user:

var user = (from u in ctx.Users
            where u.Id == 1
            select u).FirstOrDefault();

Whereas

var user = await userManager.FindByIdAsync(1);

Triggers an exception

System.Data.SqlClient.SqlException: Login failed for user 'DOMAIN\MACHINE$'.

What seems to be happening is we have the following line in our web.config configuration/system.web section

<identity impersonate="true" userName="DOMAIN\Domain User" password="xxx" />

This impersonated user has permission to access the SQL Server database but the application pool user does not. It seems that whenever I call an async method in ASP.Net Identity, it falls back to the app pool user and loses the impersonation.

I did find a similar sounding question with an explanation here https://stackoverflow.com/a/30876110/1093406

Could this also be causing my problem?

Is there any way around this apart from changing the app pool user to one that has database access?

Is using web.config to set an impersonation user an old way of doing things and now bad practice?

Edit: After further investigation I've found these articles http://www.hanselman.com/blog/AvoidUsingImpersonationInASPNET.aspx http://blog.codeishard.net/2012/09/17/await-async-mvc-and-impersonation/

Looks as though using the impersonation is a bad idea unless someone can tell me otherwise.

2

There are 2 answers

1
Mog0 On BEST ANSWER

My solution in the end was to set the user on the App Pool rather than using Impersonation. This seems to have exactly the same effect as setting impersonation in the Web.config with equivalent security, just without the problems when Async is being used.

As @Erik said in his answer, it seems that impersonation is no longer supported and according to http://www.hanselman.com/blog/AvoidUsingImpersonationInASPNET.aspx it was never encouraged in the first place.

4
Erik Funkenbusch On

Impersonation is no longer supported in Integrated Pipeline modes. Especially when using async methods.

The reason is that Impersonation happens on the thread, and when you call an async function, it may actually execute or return on a different thread.

You should use a WindowsImpersonationContext to wrap your database calls.

https://msdn.microsoft.com/en-us/library/system.security.principal.windowsimpersonationcontext(v=vs.110).aspx

using System.Security.Principal;
...

//Get the identity of the current user
IIdentity contextId = HttpContext.Current.User.Identity;
WindowsIdentity userId = (WindowsIdentity)contextId;

//Temporarily impersonate
using (WindowsImpersonationContext imp = userId.Impersonate())
{
    //Perform tasks using the caller's security context
    DoSecuritySensitiveTasks();
}

Make sure that you do this in a using block, since if an uncaught exception occurs in your code, you would end up not restoring the original context, and creating a security issue.