Sharepoint security and ASP.NET impersonation.
To make Windows security integration possible, SharePoint utilizes .NET impersonation. .NET Impersonation allows an application to run under the context of the client accessing an application. With ASP.NET impersonation, IIS is responsible for authenticating users against the domain and passing to ASP.NET an authenticated token, which can then act on behalf of the client. ASP.NET impersonation can be defined implicitly through configuration settings, or, as covered later in this article, explicitly through code. A close look at the web.config file for a SharePoint site reveals the implicit impersonation configuration for a SharePoint installation running under Integrated Windows Authentication mode:
<identity impersonate="true" />
This setting instructs ASP.NET to implicitly act on the behalf of the client who is accessing SharePoint.
The time will come during a SharePoint customization project where a developer will want .NET code to perform some action that all users of the SharePoint site do not have the permission to perform. For example, accessing and displaying data from lists on other SharePoint sites and virtual servers (through the SharePoint object model), accessing Active Directory, or pushing files to a non-public shared drive. A developer may even need to access data from a SQL Server instance that requires Windows Authentication. Some users will possess the necessary permissions to perform these operations while others won’t, and we certainly do not want to grant these permissions to everyone.
There are several steps involved with performing explicit impersonation, which I have wrapped up into a class called Impersonator (download here). The steps for impersonation are as follows:
- Authenticate a valid account which possesses the proper permissions to perform the necessary operations
- Create a new System.Security.Principal.WindowsIdentity instance that represents the account
- Begin impersonating the new Windows identity
- Perform actions that require higher permission level
- Stop impersonating and revert back to the client’s identity
The goal of wrapping these steps into one class is to write the following simple code to begin impersonation, execute code under the context of a different domain user account, and revert back to the original security context of the client:
Impersonator i = new Impersonator("SharePointRead", "MARINER", "password123").Impersonate();
With ASP.NET impersonation, the thread servicing the client request can optionally execute with the identity of the client. Let me explain it in detail.
IIS always maps a user request to some Windows account; in case of anonymous access, this is IUSR_machinename account or any other account that has been defined to be used with anonymous access; in the case of Windows authentication, this is the account whose credentials are provided by the Web site user. After successful authentication, IIS forwards this logged-in user’s identity to the ASP.NET worker thread. Now the ASP.NET worker thread has the following three options:
- It can run under the identity defined by the <processModel> tag.
- It can run under the client identity passed to it by IIS.
- It can run under the identity of the user whose credentials have been listed for impersonation.
Now the decision depends on the impersonation settings for the ASP.NET application.
- If impersonation is enabled and any specific Windows account has not been listed in the Web.config file for impersonation, then the ASP.NET worker thread runs under the client identity passed to it by IIS.
- If impersonation is not enabled, then the ASP.NET worker thread runs under the identity of the ASP.NET worker process (which has been defined by using the <processModel> tag in the Web.config file)
- If impersonation is enabled and a specific Windows account has been listed in the Web.config file for impersonation, then the ASP.NET worker thread runs under the identity generated using that account.
Impersonation for ASP.NET applications can be set up by using the <identity> tag in the Web.config file. We can specify impersonation in the following three ways:
- <identity impersonate=”true”/> This means impersonation for the ASP.NET worker thread is enabled.
- <identity impersonate=”true” name=”username” password=”password”/> This means impersonation for the ASP.NET worker thread is enabled, but the worker thread will run under the identity that will be generated by using the credentials specified by username and password attributes.
- <identity impersonate=”false”/> This means impersonation for the ASP.NET worker thread is not enabled.
ASP.NET works differently. It runs under the account that the process was started under originally. This means ASPNET or NETWORK SERVICE or if you’re using IIS 6 the account you have specifically configured for your Application Pool. So while ASP.NET provides different Authentication models to let you see who logged on to secure areas of your Web site via Forms or Windows Authentication, the underlying account in this scenario never changes. The Authentication is merely a tool for your application, but it doesn’t change the underlying security context.
This is a good thing and something that wasn’t really easily possible with classic ASP. You can however revert to the Impersonation model that works just like classic ASP by turning Impersonation on in web.config:
<identity impersonate=”true” />
<!– WS: Allow only Authenticated users –>
<!– allow users=”*”/ –>
<deny users=”?” />
Really good article on ASP.NET Impersonation and Delegation.