Skip to content

Commit ed660ef

Browse files
committed
Add trick to impersonate current Windows user in the ASP.NET application
1 parent e654b46 commit ed660ef

File tree

5 files changed

+105
-4
lines changed

5 files changed

+105
-4
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
using DemoImpersonateWindowsUserAspnet.Models;
2+
using System;
3+
using System.Web;
4+
using System.Web.Mvc;
5+
6+
namespace DemoImpersonateWindowsUserAspnet.Controllers
7+
{
8+
#if DEBUG // For security/audit reasons, you should not give the ability to impersonate a user on Production
9+
public class LogAsController : Controller
10+
{
11+
[HttpGet]
12+
public ActionResult Index()
13+
{
14+
var userNameWithoutDomain = Request.QueryString["user"];
15+
if (!string.IsNullOrEmpty(userNameWithoutDomain) && !userNameWithoutDomain.Contains(@"\"))
16+
{
17+
var userNameCookie = new HttpCookie(Constants.ImpersonateTrickCookieName) { Domain = null, Value = userNameWithoutDomain, Path = Request.ApplicationPath, HttpOnly = false };
18+
HttpContext.Response.Cookies.Add(userNameCookie);
19+
}
20+
else
21+
{
22+
// Delete cookie and go back real connected user
23+
DeleteImpersonationCookie();
24+
}
25+
return RedirectToAction("Index", "Home");
26+
}
27+
28+
[HttpGet]
29+
public ActionResult Reset()
30+
{
31+
DeleteImpersonationCookie();
32+
return RedirectToAction("Index", "Home");
33+
}
34+
35+
private void DeleteImpersonationCookie()
36+
{
37+
if (HttpContext.Response.Cookies[Constants.ImpersonateTrickCookieName] != null)
38+
{
39+
HttpContext.Response.Cookies[Constants.ImpersonateTrickCookieName].Value = null;
40+
HttpContext.Response.Cookies[Constants.ImpersonateTrickCookieName].Expires = DateTime.Now.AddMonths(-1);
41+
}
42+
}
43+
}
44+
#endif
45+
}

DemoImpersonateWindowsUserAspnet/DemoImpersonateWindowsUserAspnet/DemoImpersonateWindowsUserAspnet.csproj

+2-1
Original file line numberDiff line numberDiff line change
@@ -112,9 +112,11 @@
112112
<Compile Include="App_Start\FilterConfig.cs" />
113113
<Compile Include="App_Start\RouteConfig.cs" />
114114
<Compile Include="Controllers\HomeController.cs" />
115+
<Compile Include="Controllers\LogAsController.cs" />
115116
<Compile Include="Global.asax.cs">
116117
<DependentUpon>Global.asax</DependentUpon>
117118
</Compile>
119+
<Compile Include="Models\Constants.cs" />
118120
<Compile Include="Properties\AssemblyInfo.cs" />
119121
</ItemGroup>
120122
<ItemGroup>
@@ -156,7 +158,6 @@
156158
</ItemGroup>
157159
<ItemGroup>
158160
<Folder Include="App_Data\" />
159-
<Folder Include="Models\" />
160161
</ItemGroup>
161162
<ItemGroup>
162163
<Content Include="fonts\glyphicons-halflings-regular.woff" />

DemoImpersonateWindowsUserAspnet/DemoImpersonateWindowsUserAspnet/Global.asax.cs

+18-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
using System;
2-
using System.Collections.Generic;
3-
using System.Linq;
1+
using DemoImpersonateWindowsUserAspnet.Models;
2+
using System;
3+
using System.Security.Principal;
44
using System.Web;
55
using System.Web.Mvc;
66
using System.Web.Optimization;
@@ -17,5 +17,20 @@ protected void Application_Start()
1717
RouteConfig.RegisterRoutes(RouteTable.Routes);
1818
BundleConfig.RegisterBundles(BundleTable.Bundles);
1919
}
20+
21+
#if DEBUG // For security/audit reasons, you should not give the ability to impersonate a user on Production
22+
protected void Application_PostAuthenticateRequest(Object sender, EventArgs e)
23+
{
24+
if (HttpContext.Current.Request.Cookies[Constants.ImpersonateTrickCookieName] != null)
25+
{
26+
string userName = HttpContext.Current.Request.Cookies[Constants.ImpersonateTrickCookieName].Value;
27+
if (userName != null)
28+
{
29+
HttpContext.Current.User = new WindowsPrincipal(new System.Security.Principal.WindowsIdentity(userName, HttpContext.Current.User.Identity.AuthenticationType));
30+
}
31+
}
32+
}
33+
#endif
34+
2035
}
2136
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
namespace DemoImpersonateWindowsUserAspnet.Models
2+
{
3+
public class Constants
4+
{
5+
public const string ImpersonateTrickCookieName = "CookieImpersonateTrick";
6+
}
7+
}

README.md

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
How to impersonate user (for testing purpose) on ASP.NET application with Windows authentication
2+
================================================================================================
3+
4+
The goal of this application is to show you how to impersonate the connected Windows user on an ASP.NET application which is using Windows authentication (usually an Intranet application).
5+
6+
The Windows authentication (NTLM) is enabled in the Web.config:
7+
8+
```
9+
<system.web>
10+
<authentication mode="Windows" />
11+
</system.web>
12+
```
13+
14+
**How to impersonate another user**:
15+
16+
- Open the ASP.NET application project [DemoImpersonateWindowsUserAspnet.sln](https://github.com/ubikuity/impersonate-windows-user-aspnet/DemoImpersonateWindowsUserAspnet/DemoImpersonateWindowsUserAspnet.sln)
17+
- Run the ASP.NET application (Ctrl+F5)
18+
- To impersonate a user, add in the URL **/LogAs?user=anotherUser** (where "anotherUser" is the Windows username of the person you want to impersonate in the application)
19+
- You can act within the application as the impersonated user
20+
- To log out, type in the URL **/LogAs?reset**
21+
22+
**Notes**:
23+
24+
- **For security/audit reasons, you should not give the ability to impersonate a user on Production.**
25+
- The username of the user to impersonate should be typed without the Windows domain name: /LogAs?user=johnDoe (and not /LogAs?user=MYDOMAIN\johnDoe)
26+
27+
**Technical information:**
28+
29+
- The trick is to create a cookie containing the username we want to impersonate, then after normal Windows autentication, we redefine on the fly HttpContext.Current.User for each new request (see Global.asax.cs).
30+
31+
**References:**
32+
33+
- Inspired by [http://www.hanselman.com/blog/SystemThreadingThreadCurrentPrincipalVsSystemWebHttpContextCurrentUserOrWhyFormsAuthenticationCanBeSubtle.aspx](http://www.hanselman.com/blog/SystemThreadingThreadCurrentPrincipalVsSystemWebHttpContextCurrentUserOrWhyFormsAuthenticationCanBeSubtle.aspx)

0 commit comments

Comments
 (0)