Impersonating a User in Asp.Net - asp.net

My DBA requires all database access to be done through trusted domain account. This can be done if you set the web.config . This requires the user to login or to be on the domain for IE pass the credentials through. I want to impersonate a user by using code. I am using the code found in this knowledgebase article:
http://support.microsoft.com/kb/306158
It works great, I pass in the credentials, impersonate the user, then make the call to the database and data is returned.
The problem is if I go to another page, I lose my impersonated credentials. This means every time I make a call to the database I have to run the impersonate code.
If IIS can impersonate a domain user for all pages, then why can I not impersonate a user while using code?
It seems to be something with thread context switching. I have tried setting the alwaysFlowImpersonatingPolicy in the Aspnet.config file and it did not work.
http://msdn.microsoft.com/en-us/library/ms229553.aspx
Any suggestion? Is it even possible to do what I want?

Impersonation occurs at the level of the thread. Impersonation causes the access token of the thread, which is usually inherited from the process, to be replaced with another. The best practice is to revert the effect of impersonation and thus the token as soon as you are done with the operation(s) for which it was needed. The story is no different with IIS or ASP.NET. Each request is usually handled by a distinct thread so you will have to make each thread impersonate the user.
This means every time I make a call to
the database I have to run the
impersonate code.
So that is correct.
If IIS can impersonate a domain user
for all pages, then why can I not
impersonate a user while using code?
IIS does not do it any differently and so it may only be a perceived illusion. It cannot impersonate a user for all pages unless all pages are being served by the same thread and where the impersonated token has never been reverted as each page is served.
It seems to be something with thread
context switching.
Not really. Unless you are doing asynchronous processing (which you don't state you do in your question), the flow of the impersonation context won't be relevant. You only need to worry about flowing the impersonation context if you are causing a thread switch either directly or indirectly during the processing of a single request. If you want that the work done by a secondary (worker) thread continues to occur under the impersonation context of the primary one then you need to make sure the secondary thread borrows the impersonation token. In .NET Framework 1.1, you would have to take great care and manually orchestrate the flow of the impersonation context. With .NET 2.0, however, the ExecutionContext API was introduced and does a lot of the heavy-lifting.

The reason you're losing the impersonation context is because each time a new page request ends the impersonation context will go out of scope.
As per the docs <alwaysFlowImpersonationPolicy> is used to ensure the same impersonation context is maintained across async calls. For example when making an async call to a remote web service the callback impersonation context is the same one as the initiating thread. In the case of ASP.NET the impersonation context would only flow for the lifetime of the page request.

Related

Impersonation using httpmodule, threading issue

We have as SAAS application that runs for multiple customers at the same time. All customers use the same application, and by checking the URL used to access the application, users are redirected to the correct data for the organization.
Underwater, every organization has their own database. To make sure that users don't accidentally end up in the wrong database, we want to impersonate the request being executed to a user that only has access to the correct database. We used to do this and this worked beautifully on IIS in classic mode.
However, in integrated pipeline mode, we run into a threading issue. We use an HTTP module to impersonate the request to the correct user in the "PreRequestHandlerExecute" event. The problem that (apparently) there is no guarantee that this method is executed in the same thread as the handler that actually processes the request. This causes the impersonation to sometimes not work because the thread processing the request is not impersonated.
I've created a test project in GitHub (https://github.com/PaulVrugt/ImpersonationExample/tree/master/ImpersonationTest) demonstrating the issue (apologies for the vb.net, but you'll get the idea). When you run the example connected to an IIS using integrated pipeline mode, you'll see that sometimes the impersonated user is not used, and each time it is not used, the managedthreadid of the thread processing the request is different from the thread used in the httpmodule.
Now that I understand why it "sometimes" doesn't work, I begin to suspect I'm going about this all wrong. Is there a way to achieve what I am trying to do?
We've already tried to impersonate in the prerequesthandler in the global.asax, but that results in the same issue.

How does ASP.NET WebAPI using IIS store my users authentication state?

I have an asp.net Web Api 2 / Identity 2 application that requires a user to be authenticated. The authentication works but I notice that when I restart my local development machine and try to access a method that requires authentication then I get a failure.
As my application is unchanged from the asp.net sample then I think it uses cookies to store user data on the client. Where and how does the Server or IIS store information on which users have authenticated? Does it do this just the once or on every HTTP? Is there a difference between my using Token or cookie authentication in the way that the authentication and also authorization is checked on the server?
I think you are misunderstanding how authentication works with ASP.Net. As an example, let me show you some cookie details for a site of mine that uses Identity (note the token is actually in the cookie, the two are not mutually exclusive concepts):
Name __RequestVerificationToken
Value afeILhaIvRr56jXXXXXXXXXXX
Host site.azurewebsites.net
Path /
Expires At end of session
Note that the cookie, by default, expires at the end of your session. That means when you restart your development machine, your cookie is expired and your token is no longer valid.
In particular I have read that with token authentication then there is no need for continual re-authentication every time a request is made to the server
You need to understand that HTTP is a stateless protocol. Each request happens in a vacuum, and therefore you need to pass some data back to the server so that it can tell that the person who authenticated with Request A is really the initiator of Request B. Almost always, that piece of data is from a cookie. So, every request does indeed re-authenticate, and typically with a token in a cookie.
The only piece of data about your session that is stored on the client is the cookie (unless you are doing something atypical). The rest is on the server. How it is stored can vary:
Inproc: Easiest to setup, sessions are stored in process. So when your server or app pool is restarted, that data disappears
State Server Mode: Sessions are stored in process, but outside of the ASP.Net worker process, so the application can be restarted without losing session data
SQL Server: Unsurprisingly, this stores data in a database. Very resilient, but more work to setup. Also your best option if you are on a web farm.
ref: http://msdn.microsoft.com/en-us/library/vstudio/ms178586(v=vs.100).aspx
Expanding on the great answer by Chris, I would like to add that there are two possible models here. In forms authentication (which is the default membership type for asp.net) the cookie can either store authentication information and then it's called a ticket or the information can be stored in session, with the cookie being a simple identifier for "reconnecting" the authenticated session with the requesting client on each subsequent request.
This "reconnecting" happens in the Application_AuthenticateRequest method of the global.asax. If you are using the default forms authentication storage, i.e. an SQL DB created for you by the framework, the reconnection will be done automatically. If you are using a custom authentication store (like accessing active directory yourself or a custom users table structure) you can override the the method and reconnect the authenticated session using your own implementation. In any case, the authentication data is populated in the User.Identity object's different properties. From that point, if you use the [Authorize] attribute, the framework accesses the object to check if the user is indeed authenticated and authorized.
I any case, the authentication information is tied to both the cookie and the session. Assuming your session is InProc, like Chris said, when the session is lost (through timeout, app pool recycle or restart of the dev machine) the server-side of the session is lost and your authentication / session cookie is replaced by a new one on the next request.
EDIT: Ohh... and one more side comment. Make sure you distinguish between authentication and authorization. The client is not re-authenticated on each request. Authentication is the process of providing your credentials and being identified by the server. Authorization is, now that the server has verified who you are, on each request it checks if you are authorized to access the resource you are requesting.
The server doesn't store information about who's authenticated and who isn't. Depending on your authentication mechanism (forms, tokens?), typically, when a user logs in, the server will return some form of authentication token that the client should pass back to the server on each API call.
Without knowing more about your configuration, it's difficult to explain why when you restart your server you have to re-authenticate, it sounds like the authentication token generated by the server is invalidated on restart.
Where and how does the Server or IIS store information on which users have authenticated?
IIS does not store state based on cookie authentication. Everything is determined based on the request. Either a request has the correct encrypted information, or it doesn't. If you look at a default Forms authentication in ASP.NET, you will find a cookie called .ADUAUTH ... this cookie has all the information to authenticate the request. If the cookie is half expired, it will be reset, but that's all IIS does.
Does it do this just the once or on every HTTP?
Every HTTP request is unique, so yes, per HTTP request.
Is there a difference between my using Token or cookie authentication in the way that the authentication and also authorization is checked on the server?
It's always checked on the server: To find out more, check out: How ASP.NET Security Works: http://msdn.microsoft.com/en-us/library/ks310b8y.ASPX
I think my answer could be a little contradicting to all of the above.. But I think If I understand right..
IIS stores inside the memory space of the ASP.NET worker process, i.e the session data in the RAM.
The storing of authentication state depends on the authentication model you are using. For example: if you are using the Federated authentication, through ADFS, then when a user loads your web page he is required to sign in providing his credentials. The ADFS then sets the authentication token which is stored in the session data, the session id is stored as cookies in user's browser. The server has the mapping of Session Id to its session data.
Now the user is authenticated. The ADFS looks for authentication token to mark a user as authenticated.
When you restart the server, the session data is lost as the data is stored in RAM.
There are ways to handle this, there are 3 types of session storage:
1. InProc (Stored in memory space of ASP .NET Worker process - RAM)
2. State Server (Stored out side of ASP .NET worker process, like on cloud Azure storage)
3. SQL Server session storage (Stored in SQL server)
I think you are adopting 1, because of which you encounter the problem.
In cases 2 and 3, the session is not lost when you restart the server.
Several things --
Token based authentication is not really authentication. It is just issuing you a unique token (can be a guid, unique string, etc) and then associating it with something (like your IP address) and saving that association server side (in a database?). Now whenever you use that token, from the client app, the server checks the association already stored and serves or denies or request.
In many ways, it is very similar to using Cookies to maintain authentication. Only, token-auth was designed more for web services operation than for UIs.
In short: Out of the box, the membership provider will run it's authentication method and upon success, it will create an auth ticket/token/cookie that will be stored from the site. In addition to this, there is a session cookie that is stored with the site as well. When you make a page request, it'll pull these things and use them to determine whether or not you are already authenticated. If it finds the ticket and sees that it is still good, it'll allow access.
When you restart your local environment, the session and it's information is destroyed which is why you have to log in again.
There is an entire pipeline in the framework that makes all of this stuff happen (having to do with authentication, authorization, and identity) and there are number of ok articles on the interwebs explaining this, but imo, they're almost all incomplete or hard to follow. If you want a great soup-to-nuts explanation, PluralSight.com has some training videos that will deconstruct and explain the entire pipeline for you. Understanding the pipeline can help you implement your own custom authentication, and I highly recommend it.

Hiding passwords for impersonation

The following webpage talks about using impersonation in code (ASP.NET): http://support.microsoft.com/kb/306158. I am thinking about creating a class for the code, then the application can call impersonateValidUser and undoimpersonation.
I am concerned about putting usernames and passwords in my code as surely anyone will be able to see them using a tool like ILDASM. What is the best way to hide these passwords?
The article has a section titled: Impersonate the IIS Authenticated Account or User. I thought about creating an impersonated user in the Web.Config, but this would mean that the entire application is run as the inpersonated user. I only want a very small part of the application to run as the impersonated user - when it is necesary to access and update active directory.
I really like your intention to have have only the part of the application that does the AD updates running under a highly privileged account. I also share your concerns about storing the password in the web.config or in the code.
I can think of two options for you.
Store the account details in the web.config and encrypt that part of the web.config. That will ensure that only an administrator of the web server can get hold of the password. Someone else getting hold of the web.config won't understand a thing of the password.
Create a small, separate WCF service with the AD update code. Then run that WCF service in a separate application pool, with the app pool set to the identity of the user that has access to the active directory. Setup a restricted, localhost-only endpoint for the WCF. The WCF service should have access control to only allow access from a dedicated account. That account should be set as the identity of the app pool of the main web site.
Option 1 is easier to implement and protects the password rather well. Option 2 offers better protection for the passwords as they are not stored in the web.config at all - they are part of the IIS configuration. Option 2 also adds complete isolation between the privileged code and the rest of the system as it runs the AD update code in a separate process. With that isolation, it is much easier to make a code review for the AD code to check for security issues.

Why does IIS seem to be elevating the WindowsIdentity of one request from the AppPool to my user account?

I am currently working on an ASP .NET application which involves the user logging in using Windows Authentication. This causes both the HTTPContext.User and Thread.Principal to be set with the same credentials as the user logging in which is expected behaviour, while the WindowsIdentity stays as the IIS .NET AppPool user.
I have recently noticed in the application logs that there appears to be one request (normally the 5th-ish request on loading the page) where the WindowsIdentity starts off as the IIS user but ends up being elevated to the user who is logging in.
This only appears to be happening when the user is accessing the root path (for instance http://localhost/). If I specify any other exact path such as http://localhost/index.aspx this request does not appear to occur and the WindowsIdentity never changes.
Looking through the (rather large) codebase I can only find one method that impersonates a WindowsIdentity, but that method is not called apart from in specific circumstances on a specific page.
I was wondering why this might be happening and if there was any reason that IIS might be doing it by itself.
As per me i think the root(http://localhost) access is only for the administrator user , so it is checking where it is administrator user or not .. ,is the http://loclahost accessible if the user in not the administrator user ?

Help understanding impersonation

Could somebody please help me understand the concept of 'impersonation'?
The way I understand it is that when impersonation occurs, code executes on behalf of some identity.
So, for a web page, as long as impersonation is disabled, the web page will always run under its configured account.
If it’s enabled, I can ‘override’ its default account and set the account under which I want the web application to run.
So if I'm using IIS7 and I have the following:
- An application pool with identity set to a Custom account ‘user1’.
- An asp.net web site, with its application pool set to the one above, and with impersonation disabled.
- Windows authentication enabled.
I also have the following code:
IIdentity ii= Thread.CurrentPrincipal.Identity;
IIdentity iii = Page.User.Identity;
If I access the page, I’m asked for windows credentials, I introduce ‘user2’ credentials.
As impersonation is disabled, I’d expect the IIdentity name to be ‘user1’, which it isn’t its ‘user2’.
Can somebody help me understand what’s going on? I guess I completely misunderstand the concept of ‘impersonation’.
Thanks
UPDATE 1
I came across this link after searching for a while:
http://msdn.microsoft.com/en-us/library/aa302377.aspx
It seems like there are three IIdentity objects.
HttpContext.Current.User.Identity
Thread.CurrentPrincipal.Identity
WindowsIdentity i2 = WindowsIdentity.GetCurrent();
From the link I understand that:
HttpContext.Current.User.Identity: Represents the current user requesting the page.
Thread.CurrentPrincipal.Identity: Identity currently executing the thread. I guess that this identity will be the one under which the current web request runs and its asp.net roles will define what the user can and can’t do in the application.
I suppose most of the times both HttpContext.Current.User.Identity and Thread.CurrentPrincipal.Identity would be the same user, but for some scenarios I guess the user requesting the page and the Thread.CurrentPrincipal.Identity could be different.
Then there’s:
WindowsIdentity i2 = WindowsIdentity.GetCurrent();
The link says: “WindowsIdentity = WindowsIdentity.GetCurrent(), which returns the identity of the security context of the currently executing Win32 thread.”
After doing a few tests enabling a disabling ‘impersonation’ and for my current scenario, I find that this is the Identity that gets impersonated.
If I don’t impersonate, ‘WindowsIdentity.GetCurrent();’ would reflect the configured user in the application pool and if I do impersonate, the identity changes to the one I’ve set in web.config:
<identity impersonate="true" password="**" userName="****" />
UPDATE 2
And if I set the web.config as:
<identity impersonate="true" />
WindowsIdentity.GetCurrent() gets impersonated as the user making the request so:
HttpContext.Current.User.Identity
Thread.CurrentPrincipal.Identity
WindowsIdentity.GetCurrent()
Are the same user, the user requesting the page.
When using impersonation, ASP.NET applications can optionally execute with the identity of the client on whose behalf they are operating. The usual reason for doing this is to avoid dealing with authentication and authorization issues in the ASP.NET application code. Instead, you rely on IIS to authenticate the user and either pass an authenticated token to the ASP.NET application or, if unable to authenticate the user, pass an unauthenticated token.
From Very good Article ASP.NET Impersonation

Resources