Impersonate using Forms Authentication Impersonate using Forms Authentication asp.net asp.net

Impersonate using Forms Authentication


Impersonating a user using Forms Authentication can be done. The following code does work.

The Visual Studio Magazine article referred to by Robert is an excellent resource. There are a some issues with the example code in the article, so I've included some working code below.

Note: If you are using Visual Studio, make sure to launch it "Run as Administrator" to avoid problems with UAC blocking impersonation.

// in your login page (hook up to OnAuthenticate event)protected void LoginControl_Authenticate(object sender, AuthenticateEventArgs e){    int token;    // replace "YOURDOMAIN" with your actual domain name    e.Authenticated = LogonUser(LoginUser.UserName,"YOURDOMAIN",LoginUser.Password,8,0,out token);    if (e.Authenticated) {        Session.Add("principal", new WindowsPrincipal(new WindowsIdentity(new IntPtr(token))));    }}[DllImport("advapi32.dll", SetLastError = true)]public static extern bool LogonUser(string lpszUsername, string lpszDomain, string lpszPassword,    int dwLogonType, int dwLogonProvider, out int TokenHandle);// in global.asax.csvoid Application_PreRequestHandlerExecute(object send, EventArgs e){    if (Thread.CurrentPrincipal.Identity.IsAuthenticated == true && HttpContext.Current.Session != null) {        WindowsPrincipal windowsPrincipal = (WindowsPrincipal)Session["principal"];        Session["principal"] = (GenericPrincipal)Thread.CurrentPrincipal;        Thread.CurrentPrincipal = windowsPrincipal;        HttpContext.Current.User = windowsPrincipal;        HttpContext.Current.Items["identity"] = ((WindowsIdentity)windowsPrincipal.Identity).Impersonate();    }}// in global.asax.csvoid Application_PostRequestHandlerExecute(object send, EventArgs e){    if (HttpContext.Current.Session != null && Session["principal"] as GenericPrincipal != null) {        GenericPrincipal genericPrincipal = (GenericPrincipal)Session["principal"];        Session["principal"] = (WindowsPrincipal)Thread.CurrentPrincipal;        Thread.CurrentPrincipal = genericPrincipal;        HttpContext.Current.User = genericPrincipal;        ((WindowsImpersonationContext)HttpContext.Current.Items["identity"]).Undo();    }}// test that impersonation is working (add this and an Asp:Label to a test page)protected void Page_Load(object sender, EventArgs e){    try {        // replace YOURSERVER and YOURDB with your actual server and database names        string connstring = "data source=YOURSERVER;initial catalog=YOURDB;integrated security=True";        using (SqlConnection conn = new SqlConnection(connstring)) {            conn.Open();            SqlCommand cmd = new SqlCommand("SELECT SUSER_NAME()", conn);            using (SqlDataReader rdr = cmd.ExecuteReader()) {                rdr.Read();                Label1.Text = "SUSER_NAME() = " + rdr.GetString(0);            }        }    }    catch {    }}

Update:

You should also handle Application_EndRequest, because calls like Response.End() will bypass Application_PostRequestHandlerExecute.

Another issue is that the WindowsIdentity may get garbage collected, so you should create a new WindowsIdentity and WindowsPrincipal from the logon token on every request.

Update2:

I'm not sure why this is getting downvoted, because it works. I've added the pinvoke signature and some test code. Again, launch Visual Studio using "Run as Administrator". Google how to do that if you don't know how.


If your users are using IE then you can turn on integrated security for the website and your users will be authenticated silently (no login dialog, no login page). Your impersonation will then work. If you need to target other browsers then this may not work (the user will probably be presented with a login dialog).

Your current impersonation will never work because your users are logging in using an account other than their domain account. You can't expect the site to impersonate a user which hasn't supplied his credentials. That would go against basic security principals.


You may find this useful:

EDIT

On reading your question more closely, I am not sure if that approach would work with your scenario though; when you login using Forms Authentication and Impersonate Active Directory user