4

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.

Community
  • 1
  • 1
Mog0
  • 1,689
  • 1
  • 16
  • 40
  • 1
    [This](http://stackoverflow.com/questions/25294709/async-await-with-entity-framework-6-1-1-and-impersonation) may help – Yuval Itzchakov Jun 26 '15 at 17:16
  • @Yuval That does look like the same problem as I am having but the web app I'm developing will be installed on IIS servers by IT departments of other companies (who have varying levels of skill) and the IIS servers may also host other apps so modifying any global settings is not practical. Good to know I'm not the only person having these problems though. – Mog0 Jun 26 '15 at 21:40
  • web.config isn't a global setting; its only applicable to the application pool running the application in question. – Claies Jun 26 '15 at 21:51
  • @Claies I hadn't noticed that it said web.config. I had found that setting earlier and tried it unsuccessfully in the web.config (it didn't affect the setting when I checked with SecurityContext.IsFlowSuppressed) and this https://msdn.microsoft.com/en-us/library/6bs4szyc(v=vs.110).aspx says that it only works for the iis aspnet.config. – Mog0 Jun 26 '15 at 22:52

2 Answers2

2

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.

Erik Funkenbusch
  • 92,674
  • 28
  • 195
  • 291
  • Do you have a source for the "no longer supported in Integrated Pipeline modes"? – Mog0 Jun 26 '15 at 21:21
  • Wrapping the database calls is not possible as the database calls are in ASP.Net Identity / Entity framework, which is the source of my problems. I need to investigate further but I may be able to remove the impersonation and instead change the app pool identity. The web application predates me at my company and has always used the web.config impersonation, I need to check if there's a technical reason why. – Mog0 Jun 26 '15 at 21:32
  • @Mog0 - That makes no sense. You can't use non-Windows identities to impersonate, so either your identities are based on Windows Identities, or they're based on non-windows identities, and you can't impersonate a non-windows identity, so therefore your connection to your database would not work. If you're going to use a specific network user to access the database, then just set the App Pool identity to use the identity you need. – Erik Funkenbusch Jun 27 '15 at 00:34
  • Setting the app pool user would be equivalent to setting the impersonation user in web.config but our product is installed at customer sites, sometimes by IT people who aren't always as technical as they should be. Issues would be how easy it would be for us to automatically set the app pool user (setting web.config is easy) and if any customers would have any policies preventing It (some have bizarre restrictions). – Mog0 Jun 27 '15 at 07:10
1

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.

Mog0
  • 1,689
  • 1
  • 16
  • 40
  • Lost an entire day trying to make an impersonation work, and all i had to do was change the identity directly at the app pool..... – L4marr May 26 '22 at 19:23