J.D. Meier, Alex Mackman, Blaine Wastell, Prashant Bansode, Andy Wigley, Kishore Gopalan
Microsoft Corporation
August 2005
Applies To
- ASP.NET version 2.0
- Microsoft® Windows Server™ 2003 operating system
- Microsoft Windows® 2000 operating system
Summary
This How To shows you how and when you should use impersonation in ASP.NET 2.0 applications. By default, impersonation is turned off, and you can access resources by using the ASP.NET Web application's process identity. However, you can use impersonation to access local resources and perform operations by using the authenticated user's identity or by using a specific Windows identity. You can enable impersonation programmatically or by applying appropriate configuration settings in the Web.config file.
Delegation allows you to use an impersonation token to access network resources. Your ability to use delegation depends on your selected authentication mechanism and appropriate account configuration. You should be careful when you use impersonation and delegation because of the additional security and scalability issues it can cause.
Contents
Objectives
Overview
What's New in 2.0
Impersonation Scenarios
Impersonating the Original Caller
Impersonating the Original Caller Temporarily
Impersonating by Using LogonUser
Impersonating by Using the WindowsIdentity Constructor
Impersonating a Fixed Identity
Delegation
Impersonation / Delegation vs. Trusted Subsystem
Delegation Table
Windows 2000 Server Considerations
Windows Server 2003 Considerations
Additional Resources
Objectives
- Learn what's new in ASP.NET version 2.0 impersonation.
- Configure your Web application to impersonate the original caller.
- Configure your Web application to impersonate a specific Windows identity.
- Impersonate the original caller programmatically to run specific code under an impersonated identity in your Web application.
- Use delegation to access network resources.
Overview
By default, ASP.NET does not use impersonation, and your code runs using the ASP.NET application's process identity. On the Microsoft® Windows Server™ 2003 operating system, ASP.NET applications run in an Internet Information Services (IIS) 6.0 application pool by default. The IIS application pool runs under the NT AUTHORITY\Network Service identity. On the Microsoft Windows® 2000 Server operating system with IIS 5.0 or on Windows Server 2003 with IIS 6.0 configured for IIS 5.0 isolation mode, ASP.NET applications run in a worker process that uses the local ASPNET account identity.
Because impersonation is disabled, the application gains access to all resources by using the process identity. Any Windows resources, such as files and registry keys, must have an access control list (ACL) that grants access to the process identity.
If you need to access resources by using the authenticated caller's identity or by using a specific Windows identity other than the process identity, you can configure your ASP.NET application to use impersonation. If you need to impersonate at the method level to perform specific operations or access particular resources, then you can use programmatic impersonation by using the WindowsIdentity.Impersonate method.
LogonUser vs. WindowsIdentidy(userPrincipalName)
If your application authenticates callers by using custom authentication, such as forms authentication, then you cannot impersonate the original caller through ASP.NET configuration. Instead you must call the Impersonate method of a WindowsIdentity object that you create for the original caller. You can obtain an impersonation token for the original caller, provided that the caller has a Windows account, by calling the Win32 LogonUser API (on Windows 2000 Server or Windows Server 2003) or by using a special form of the WindowsIdentity constructor that takes a single parameter of a user principal name (UPN). The technique you should use depends on the following:
- If your server is running Windows 2000 Server, you must use the Win32 LogonUser API. The extensions to the Kerberos protocol used by the WindowsIdentity(userPrincipalName) constructor are not available on Windows 2000 Server.
- If you are impersonating a local account, you must use LogonUser.
- If your server is running Windows Server 2003, you have the following choices:
- If your application has access to the user name and password of the caller (perhaps through a logon Web page) and needs to access local resources, you should use the Win32 LogonUser API. This is preferable to using the WindowsIdentity constructor because you do not need to grant the ASP.NET process account the "Act as part of the operating system" privilege.
- If your application has access to the user name only, you must use the WindowsIdentity constructor. However, if your application needs to access local resources, you must grant the ASP.NET process account the "Act as part of the operating system" privilege.
What's New in 2.0
In ASP.NET 2.0 applications, you can now change the default behavior to flow the impersonation token to newly created threads, when you create the thread with any of the managed threading techniques (such as Thread.Start, an asynchronous delegate, or QueueUserWorkItem). With .NET Framework 1.1, you have to manually propagate impersonation tokens to new threads you create.
The impersonation token does not propagate across threads if you use COM interop with components that have incompatible threading models, or if you use unmanaged techniques to create new threads (for example, when you use the Win32 CreateThread API). In these situations, the behavior is the same as in .NET Framework 1.1. For more information, see, PRB: 'Access Denied' Error Message Occurs When You Impersonate an Account in ASP.NET and then Call STA COM Components.
Impersonation Scenarios
The most common situations where you might require impersonation and delegation are:
- Impersonating the original caller. You want to access Windows resources that are protected with ACLs configured for your application's domain user accounts.
- Impersonating the original caller programmatically. You want to access resources predominantly by using the application's process identity, but specific methods need to use the original caller's identity.
- Impersonating a specific Windows identity. You need to use a specific identity or several Windows identities to access particular resources.
- Using delegation to access network resources by using an impersonated identity. You need to use an impersonated identity to access remote resources.
This How To shows you when and how to use each approach on Windows Server 2003 and on Windows 2000 Server.
Impersonating the Original Caller
If you need to access local resources, such as the file system or a local database, while assuming the identity of the original caller (the authenticated user), you need to use an appropriate IIS authentication type. Ideally, you should use IIS to configure your application's virtual directory for integrated Windows authentication, and then configure your ASP.NET application for Windows authentication and impersonation. This approach is shown in Figure 1.
Figure 1. Impersonating the original caller
This configuration is generally required if you need to control access to Windows resources with ACLs set against the individual user of your application.
To impersonate the original caller, you need to use IIS to configure appropriate authentication for your application's virtual directory and use appropriate configuration in the Web.config file.
To impersonate the original caller
- Configure IIS as follows:
- Right-click your Web site, and then click Properties.
- Click the Directory Security tab.
- Click the Edit button in the Authentication and access control panel.
- Select Integrated Windows authentication and clear all other check boxes.
Note While you could also select basic or digest authentication, integrated Windows authentication is recommended in this scenario.
- Configure your ASP.NET application by adding the following configuration to the <system.web> section of your application's Web.config file.
<authentication mode="Windows" />
<identity impersonate="true" />
With this configuration, ASP.NET impersonates the IIS authenticated user, and the ASP.NET request threads that execute your Web application's code have the impersonation token attached to them. IIS passes a Windows token for the authenticated user to ASP.NET. The token can represent the authenticated user, if IIS is configured for Integrated Windows authentication, or another form of authentication such as basic, digest, or client certificate authentication. The token represents the anonymous user identity (IUSR_MACHINENAME) if IIS is configured to enable anonymous access.
While the above configuration ensures that all resource access is performed using the identity of the original caller, if you need to access specific resources such as local files by using the process identity, you can temporarily remove the impersonation token from the ASP.NET request thread by using the following code:
// Stop impersonation
WindowsImpersonationContext ctx = WindowsIdentity.Impersonate(IntPtr.Zero);
try
{
// Thread is now running under the process identity.
// Any resource access here uses the process identity.
}
finally
{
// Resume impersonation
ctx.Undo();
}
Impersonating the Original Caller Temporarily
If you need to use the process identity for most resource access, and then impersonate the original caller to perform specific operations or to access specific resources, you need to use programmatic impersonation. (See Figure 2.)
Figure 2. Using programmatic impersonation to temporarily impersonate the original caller.
To temporarily impersonate the original caller within a particular method, you need to obtain the WindowsIdentity object that represents the authenticated user, and then call its Impersonate method.
To temporarily impersonate the original caller
- Ensure that impersonation is disabled for your ASP.NET application; for example, by using the following configuration in the Web.config file:
<identity impersonate="false" />
Note By default, impersonation is disabled for all ASP.NET applications.
- Add the following code to the method that requires impersonation.
using System.Security.Principal;
...
// Obtain the authenticated user's Identity
WindowsIdentity winId = (WindowsIdentity)HttpContext.Current.User.Identity;
WindowsImpersonationContext ctx = null;
try
{
// Start impersonating
ctx = winId.Impersonate();
// Now impersonating
// Access resources using the identity of the authenticated user
}
// Prevent exceptions from propagating
catch
{
}
finally
{
// Revert impersonation
if (ctx != null)
ctx.Undo();
}
// Back to running under the default ASP.NET process identity
This code impersonates the original caller. The original caller's identity is maintained in the HttpContext.Current.User.Identity object.
Exception Handling
Notice how the preceding code uses a finally block to ensure that impersonation is reverted even in the event of an exception. The code also uses a catch block to ensure that an exception cannot propagate itself up the call stack while the thread is impersonating.
Impersonating by Using LogonUser
If your users have Windows domain accounts, but you are using custom authentication, such as forms authentication, IIS does not authenticate the caller and it passes a logon token that represents the anonymous user account to ASP.NET. To impersonate the caller in this instance, you must programmatically create a WindowsIdentity object for the caller, which you can use to impersonate. Create a WindowsIdentity object either by using a logon token returned from the Win32 LogonUser API, or by using the WindowsIdentity(userPrincipalName) constructor that takes a single parameter of a user principal name (UPN). The underlying extensions for the Kerberos protocol required by this constructor are only available on Windows Server 2003. For more information, see the section Impersonating by Using the WindowsIdentity Constructor in this document.
You can create a Windows token and associated logon session for a domain or local account by using the Win32 LogonUser API. You must pass the user name and password to this API, together with other parameters including the type of logon session you require.
Note You should protect the credentials passed to LogonUser by encrypting them.
You can impersonate with the returned token and check which Windows groups the user is a member of. Whether you can access local resources or network resources depends on the logon session type that you request (you specify the logon session type in the third argument of LogonUser). The most commonly used logon session types when calling this API are the following:
- Interactive logon. If you need to access remote resources, request an interactive logon session. This results in a logon session that has network credentials. The user account passed to logon user must be granted the Log on locally user right.
- Network logon: This establishes a logon session with no network credentials. This means you can impersonate the token and access local resources only. The user account passed to logon user must be granted the Access this computer from the network user right. By default, all accounts have this right because it is granted to the Everyone group.
To check whether you have the Access this computer from the network user right
- From the Start menu, click Control Panel.
- Click Administrative Tools.
- Click Local Security Policy.
- Expand Local Policies and click User Rights Assignments.
- Double-click Access this computer from the network to see the user accounts and groups that have this right assigned. If necessary, click the Add User or Group button to add the account you wish to impersonate.
Note The name of the network logon session type sometimes causes confusion. It is called a network logon because it is equivalent to a user accessing the local computer from somewhere else on the network. The resulting logon session does not have network credentials, and therefore cannot be used to access network resources.
When you request an interactive logon, LogonUser returns a primary token that allows you to create processes while impersonating. When you request a network logon, LogonUser returns an impersonation token that can be used to access local resources, but not to create processes. If required, you can convert an impersonation token to a primary token by calling the Win32 DuplicateToken function.
The following example shows how to use the Win32 LogonUser API, construct a WindowsIdentity object from the token, attach the token to the current thread to begin impersonation, and then cancel the impersonation.
<%@ Page Language="C#" %>
<%@ Import Namespace="System.Security.Principal" %>
<%@ Import Namespace="System.Runtime.InteropServices" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<script runat="server">
// Declare signatures for Win32 LogonUser and CloseHandle APIs
[DllImport("advapi32.dll", SetLastError = true)]
static extern bool LogonUser(
string principal,
string authority,
string password,
LogonSessionType logonType,
LogonProvider logonProvider,
out IntPtr token);
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool CloseHandle(IntPtr handle);
enum LogonSessionType : uint
{
Interactive = 2,
Network,
Batch,
Service,
NetworkCleartext = 8,
NewCredentials
}
enum LogonProvider : uint
{
Default = 0, // default for platform (use this!)
WinNT35, // sends smoke signals to authority
WinNT40, // uses NTLM
WinNT50 // negotiates Kerb or NTLM
}
protected void logonUserbtn_Click(object sender, EventArgs e)
{
IntPtr token = IntPtr.Zero;
WindowsImpersonationContext impersonatedUser = null;
try
{
// Create a token for DomainName\Bob
// Note: Credentials should be encrypted in configuration file
bool result = LogonUser("Bob", "DomainName",
"P@ssw0rd",
LogonSessionType.Network,
LogonProvider.Default,
out token);
if (result)
{
WindowsIdentity id = new WindowsIdentity(token);
// Begin impersonation
impersonatedUser = id.Impersonate();
// Log the new identity
Response.Write(String.Format(
"</p>Identity after impersonation: {0}<br>",
WindowsIdentity.GetCurrent().Name));
// Resource access here uses the impersonated identity
}
else
{
Response.Write("</p>LogonUser failed: " +
Marshal.GetLastWin32Error().ToString());
}
}
catch
{
// Prevent any exceptions that occur while the thread is
// impersonating from propagating
}
finally
{
// Stop impersonation and revert to the process identity
if (impersonatedUser != null)
impersonatedUser.Undo();
// Free the token
if (token != IntPtr.Zero)
CloseHandle(token);
}
// Verify the old process identity
Response.Write(String.Format("</p>Identity after Undo: {0}<br>",
WindowsIdentity.GetCurrent().Name));
}
</script>
<html >
<head runat="server">
<title>LogonUser Test Page</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:Button ID="logonUserbtn" runat="server" OnClick="logonUserbtn_Click" Text="LogonUser" /></div>
</form>
</body>
</html>
The preceding example passes LogonSessionType.Network to LogonUser. This results in a network logon session which has no network credentials. If you need a token and logon session that you can use to access network resources use LogonSessionType.Interactive. For more information, see Delegation in this document.
For clarity, the code example shown above uses literal strings to specify the credentials passed to LogonUser. If you use LogonUser, you should store the credentials that you pass to the method in encrypted format in your Web.config file. Store credentials in the <appSettings> section as shown in the following example, and then use the Aspnet_regiis.exe utility and a protected configuration provider to encrypt this section.
<appSettings>
<add key="ImpIdentity" value="Domainname\Username;secretpassword"/>
</appSettings>
The following example shows how to access this configuration data to pass to LogonUser.
string domain;
string username;
string password;
// Access the <appSettings> value
string[] userAndPassword = ((string)ConfigurationManager.AppSettings["ImpIdentity"]).Split(';');
// Parse out the domain, username and password
domain = userAndPassword[0].Substring(0, userAndPassword[0].IndexOf(@"\"));
userName = userAndPassword[0].Substring(userAndPassword[0].IndexOf(@"\")+1);
password = userAndPassword[1];
// Call LogonUser
bool result = LogonUser(userName, domain, password, LogonSessionTypes.Network,
LogonProviders.Default, out token);
For more information about encrypting the configuration file sections, see:
- How To: Encrypt Configuration Sections in ASP.NET 2.0 Using DPAPI
- How To: Encrypt Configuration Sections in ASP.NET 2.0 Using RSA
Using LogonUser on Windows Server 2003
When you use the LogonUser API for impersonation on Windows Server 2003, you do not need to grant your application's process identity the Act as part of the operating system user right.
On Windows Server 2003, instead of using LogonUser, you can generate a token by using the WindowsIdentity constructor. The advantage of this approach is that you do not have to store credentials on your Web server. The downside is that to get an impersonate-level token to use to access local resources, your process identity requires the Act as part of the operating system user right. For more information, see the section, Impersonating by Using the WindowsIdentity Constructor in this document.
Using LogonUser on Windows 2000 Server
When you use the LogonUser API for impersonation on Windows 2000 Server, you must grant the application's process account the Act as part of the operating system privilege. You should avoid this approach if possible to avoid raising the privileges of your Web application.
Impersonating by Using the WindowsIdentity Constructor
One of the overloads for the constructor on the WindowsIdentity class permits you to obtain a Windows token and logon session for a given domain account by supplying a user principal name (UPN). With this approach (shown in the following example), you do not need the account's password.
using System.Security.Principal;
...
WindowsIdentity wi = new WindowsIdentity(userName@fullyqualifieddomainName);
WindowsImpersonationContext ctx = null;
try
{
ctx = wi.Impersonate();
// Thread is now impersonating
}
catch
{
// Prevent exceptions propagating.
}
finally
{
// Ensure impersonation is reverted
ctx.Undo();
}
This WindowsIdentity constructor relies on a Windows Server 2003 extension to the Kerberos protocol called Service for User to Self (S4U2Self). You can use this approach if your application runs on a Windows Server 2003 in a Windows Server 2003 domain. The advantage of this approach is that you do not have to store credentials as you do for LogonUser. However, the disadvantage is that if your code needs to access local resources, you must grant the Act as part of the operating system privilege to your Web application process account to get an impersonation-level token.
To grant the Act as part of the operating system privilege
- On the Start menu, click Control Panel.
- Click Administrative Tools.
- Click Local Security Policy.
- Expand Local Policies, and then click User Rights Assignments.
- In the right pane, right-click Act as part of the operating system, and then click Properties.
- Click the Add User or Group button, then enter the account used to run your ASP.NET application (Network Service by default).
Token Types
The type of token generated with the S4U2Self extension determines what you can do with the token while impersonating. You can obtain the following token types:
- Identify-level token. This is returned by default. With this type of token, you can check to see what groups are contained in the token, but you cannot use it as an impersonation token to access local or remote resources.
- Impersonation-level token. If you grant your process account the "Act as part of the operating system" user right, you get this type of token from the WindowsIdentity constructor. With this type of token, you can impersonate with it and access local resources.
Note This places your process within the trusted computing base (TCB) of the Web server, which makes your Web server process very highly privileged. Where possible, you should avoid this approach because an attacker who manages to inject code and compromise your Web application will have almost unrestricted capabilities on the local computer.
- Delegate-level token. If you configure your service or machine account in Active Directory to be trusted for constrained delegation, you will get a token that you can use to access network resources.
Note You will typically need TCB when accessing a remote service. For local resources, the TCB privilege controls access. For remote service access, TCB is not required, but an identify-level token will usually be insufficient. Therefore, you will need TCB to generate an identify-level token. For example, if you use ADO.NET to communicate with a remote SQL Server database, the call will fail before it leaves the Web server due to the local resources such as performance counters (and therefore registry keys) that the SQL Server managed data provider needs to access.
Impersonating a Fixed Identity
If you need to impersonate the same identity throughout the lifetime of your application, you can specify credentials on the <identity> element in your Web.config file. The following example shows how to impersonate a Windows account with the name TestUser.
<identity impersonate="true" username="TestUser" password="P@ssw0rd" />
If you use this approach, you should encrypt the credentials. With ASP.NET version 2.0, you can use the Aspnet_regiis.exe tool. With ASP.NET version 1.1, you can use the Aspnet_setreg.exe tool.
To encrypt the <identity> element by using Aspnet_regiis
- Run the following command to encrypt the <identity> element in the Web.config file.
aspnet_regiis -pef "system.web/identity" " C:\Sites\IntranetSite"
To decrypt the <identity> element
- Run the following command to revert the <identity> element to plain text.
aspnet_regiis -pdf "system.web/identity" " C:/Sites/IntranetSite "
Note that the above commands use the default protected configuration provider named, which uses RSA encryption. To choose an alternative provider, add the -prov option naming the required provider. If your application runs in a Web farm, you should generally use the RSA provider. For more information about how to use DPAPI and RSA encryption and advice about when to use machine-level key storage versus user-level key storage, see:
- How To: Encrypt Configuration Sections in ASP.NET 2.0 Using DPAPI
- How To: Encrypt Configuration Sections in ASP.NET 2.0 Using RSA
Using Fixed Identities on Windows Server 2003
You can configure credentials on the <identity> element on Windows 2000 Server or Windows Server 2003 to use a fixed identity for resource access on ASP.NET applications. However, if you are running on Windows Server 2003 with IIS 6.0 configured to run in worker isolation mode (the default), you can avoid impersonation by configuring your ASP.NET application to run in a custom application pool that runs under a specific domain identity. For more information, see How To: Create a Service Account for an ASP.NET 2.0 Application.
Delegation
To obtain an impersonation token so that you can access network resources, you have a number of options.
- Use Kerberos authentication and delegation. If you use Kerberos to authenticate your users, you can impersonate the original caller by using the techniques described in the sections "Impersonating the Original Caller" and "Impersonating the Original Caller Temporarily" and use Kerberos delegation to gain access to network resources. To do so:
- If your application runs under the Network Service account, you need to configure your computer account in Active Directory to be trusted for delegation.
- If your application runs under a custom domain account, you need to configure your domain account in Active Directory to be trusted for delegation. You must also register a service principal name in Active Directory to associate the domain account with the HTTP service on your Web server.
If you use domain accounts to run your Web application or the downstream service that you are accessing, you must also ensure that appropriate service principal names (SPNs) are created in Active Directory for those accounts. For more information, see How To: Use Protocol Transition and Constrained Delegation with ASP.NET 2.0.
- Call LogonUser and request an Interactive logon session. An interactive logon session has network credentials that allow you to authenticate against network servers. Use this approach when you cannot use Kerberos authentication to authenticate your users, and when you cannot use protocol transition.
Note that you must have access to both the user name and password to call LogonUser. You can only use the token to access network resources over a single hop, whereas Kerberos delegation allows the impersonated identity to flow across multiple tiers.
- Use protocol transition. With this approach, you use a non-Kerberos authentication mechanism to authenticate your users, and then use the new WindowsIdentity constructor to obtain a Windows token for the user on the server. Use this approach when you cannot use Kerberos authentication to authenticate your users, for example because they connect to your application over the Internet, but your users do have Windows domain accounts. To get a delegate-level token with this approach, you must be running on a Windows Server 2003 in a Windows 2003 domain and you need to configure your computer or process account in Active Directory as trusted for delegation and protocol transition. For more information, see How To: Use Protocol Transition and Constrained Delegation with ASP.NET 2.0.
- Use basic authentication and impersonation. With basic authentication, the user name and password of the user are available in clear text on the server. When IIS authenticates a caller by using basic authentication, it creates a token that contains these credentials. The token can be used for network access. As result, if you configure your application to impersonate the original caller by using the <identity> element or impersonate programmatically by using WindowsIdentity.Impersonate, you can access network resources while impersonating.
Use basic authentication if you cannot use Kerberos authentication and delegation, and you cannot use LogonUser or protocol transition. For example, if you configure IIS to use integrated Windows authentication, it will use Kerberos authentication if possible, but otherwise default to NTLM authentication—which does not allow access to network resources with an impersonated identity. If you cannot use the new WindowsIdentity constructor because you are not running on a Windows Server 2003 in a Windows 2003 domain, and you do not have access to the users password to call LogonUser, then basic authentication provides a solution. However, with basic authentication, the user's credentials pass through the network in clear text. Therefore, you should be sure that all network connections are secured with SSL or IPSEC.
Impersonation / Delegation vs. Trusted Subsystem
When you design the authentication that you require in your application, consider whether to use impersonation to use the original caller's identity for access to back-end resources, or whether to use the trusted subsystem model, where the Web or application server is responsible for authenticating users and the server then uses a service identity to access back-end resources. The two techniques have different advantages and disadvantages as explained in the following subsections.
Trusted Subsystem
A trusted subsystem model is where the database server trusts the Web application identity. The Web application identity is trusted to make calls on behalf of the original caller. (See Figure 3.)
Figure 3. Trusted subsystem model
Trusted Subsystem Advantages
The advantages of the trusted subsystem model include:
- Scalability. The trusted subsystem model supports efficient connection pooling. Connection pooling allows multiple clients to reuse available pooled connections. Connection pooling works with this model because all back-end resources accessed use the security context of the application's service account, regardless of the caller's identity.
- Minimal back-end ACL management. Only the service account accesses back-end resources (for example, databases). ACLs are configured for this single identity.
- No direct data access. In the trusted subsystem model, only the service account is granted access to the back-end resources. As a result, users cannot directly access back-end data without going through the application (and being subjected to application authorization).
Trusted Subsystem Disadvantages
The trusted subsystem model has the following disadvantages:
- Auditing. To perform auditing at the back end, you can explicitly pass (at the application level) the identity of the original caller to the back end, and have the auditing performed there. With this approach, you have to trust the middle tier and you have a potential repudiation risk. Alternatively, you can generate an audit trail in the middle tier, and then correlate it with back-end audit trails. To use this approach, you must ensure that the server clocks are synchronized.
- Increased risk from server compromise. In the trusted subsystem model, the middle-tier service is granted broad access to back-end resources. As a result, a compromised middle-tier service could make it easier for an attacker to gain broad access to back-end resources.
Impersonation / Delegation
The impersonation and delegation model also has advantages and disadvantages.
Impersonation / Delegation Advantages
The advantages of the impersonation / delegation model include:
- Auditing. You benefit from operating system auditing. This allows administrators to track which users have attempted to access specific resources.
- Auditing across tiers. The user's security context is maintained across the physical tiers of your application, which allows administrators to audit across tiers. Generally, auditing is considered most authoritative if the audits are generated at the precise time of resource access and by the same routines that access the resource.
- Granular access controls. You can configure granular access in the database. You can restrict individual user accounts independently of one another in the database.
Impersonation / Delegation Disadvantages
The disadvantages of the impersonation / delegation model include:
- Scalability. The impersonation / delegation model does not allow you to make efficient use of database connection pooling because database access is performed by using connections that are tied to the individual security contexts of the original callers. This significantly limits the application's ability to scale to large numbers of users.
- Increased administration effort. ACLs on back-end resources need to be maintained in such a way that each user is granted the appropriate level of access. When the number of back-end resources increases (and the number of users increases), a significant administration effort is required to manage ACLs.
Delegation Table
The IIS authentication type that you use affects whether or not you can impersonate the original caller and use the impersonation token to access network resources. To do so requires delegation. Table 1 shows the various IIS authentication types and whether or not you can impersonate the caller to access network resources.
Table 1: IIS Authentication Types and Delegation Capability
Authentication Type | Can Delegate | Notes |
---|---|---|
Anonymous | Depends | If the anonymous account (by default IUSR_MACHINE) is configured in IIS as a local account, it cannot be delegated unless the local (Web server) and remote computer have identical local accounts (with matching user names and passwords). If the anonymous account is a domain account it can be delegated. |
Basic | Yes | If Basic authentication is used with local accounts, it can be delegated if the local accounts on the local and remote computers are identical. Domain accounts can also be delegated. |
Digest | No | |
Integrated Windows | Depends | Integrated Windows authentication either results in NTLM or Kerberos (depending upon the version of operating system on client and server computer). NTLM does not support delegation. Kerberos supports delegation with the appropriate Active Directory configuration. |
Client Certificates | Depends | Can be delegated if used with IIS certificate mapping and the certificate is mapped to a local account that is duplicated on the remote computer or is mapped to a domain account. This works because the credentials for the mapped account are stored on the local server and are used to create an Interactive logon session (which has network credentials). Active Directory certificate mapping does not support delegation. |
Windows 2000 Server Considerations
Keep the following in mind if you are using Windows 2000 Server.
- Calling LogonUser on Windows 2000 Server requires that the process account is granted the Act as part of the operating system privilege. You should avoid this if possible.
- You cannot use the new WindowsIdentity constructor that accepts a UPN to construct a token on Windows 2000 Server. Internally, this constructor uses the LsaLogonUser API with the KERB_S4U_LOGON flag. This flag is only available with Windows Server 2003.
Windows Server 2003 Considerations
Keep the following in mind if you are using Windows Server 2003:
- Windows Server 2003 introduces constrained delegation. Kerberos delegation on Windows 2000 Server is unconstrained. Servers that are configured as trusted for delegation in Active Directory can access any network resources or any machine on the network while using the impersonated user's security context. This represents a potential security threat, particularly if the Web server is compromised. With constrained delegation on Windows Server 2003, administrators can specify exactly which services on which servers a computer can access by using the impersonated user's security context.
For more information, see How To: Use Protocol Transition and Constrained Delegation.
- WindowsIdentity vs. LogonUser. To obtain an impersonation token on Windows Server 2003, you can use the new WindowsIdentity constructor or you can call the LogonUser API. The drawback with LogonUser is that you are forced to store credentials. However, if you use the WindowsIdentity constructor to obtain an impersonation-level token with which you can access local resources, you must grant your process identity the "Act as part of the operating system" user right. . For most common scenarios where you need to access remote resources—for example, by using the SQL Server managed data provider—you also require this user right. You do not need to grant the "Act as part of the operating system" user right if you only want to use the token to check group membership.
Additional Resources
- How To: Use Protocol Transition and Constrained Delegation with ASP.NET 2.0
- How To: Use Windows Authentication in ASP.NET 2.0
- How To: Encrypt Configuration Sections in ASP.NET 2.0 Using DPAPI
- How To: Encrypt Configuration Sections in ASP.NET 2.0 Using RSA
Feedback
Provide feedback by using either a Wiki or e-mail:
- Wiki. Security Guidance Feedback Wiki page: http://channel9.msdn.com/wiki/default.aspx/Channel9.SecurityGuidanceFeedback
- E-mail. Send e-mail to secguide@microsoft.com.
We are particularly interested in feedback regarding the following:
- Technical issues specific to recommendations
- Usefulness and usability issues
Technical Support
Technical support for the Microsoft products and technologies referenced in this guidance is provided by Microsoft Support Services. For product support information, please visit the Microsoft Support Web site at http://support.microsoft.com/.
Community and Newsgroups
Community support is provided in the forums and newsgroups:
- MSDN Newsgroups: http://msdn.microsoft.com/newsgroups/default.asp
- ASP.NET Forums: http://forums.asp.net/
To get the most benefit, find the newsgroup that corresponds to your technology or problem. For example, if you have a problem with ASP.NET security features, you would use the ASP.NET Security forum.
Contributors and Reviewers
- External Contributors and Reviewers: Jason Taylor, Security Innovation; Rudolph Araujo, Foundstone Professional Services
- Microsoft Consulting Services and PSS Contributors and Reviewers: Adam Semel, Tom Christian, Wade Mascia
- Microsoft Product Group Contributors and Reviewers: Stefan Schackow
- Test team: Larry Brader, Microsoft Corporation; Nadupalli Venkata Surya Sateesh, Sivanthapatham Shanmugasundaram, Infosys Technologies Ltd.