I think I get it. My solution is to set a cookie with a drop down list and refresh the page. Read the cookie value in the event Application_AuthenticateRequestand replace as HttpContext.Userrequested by the user, if necessary. Here is the code:
Select a user as follows:
<select id="LoginUser" name="LoginUser" onchange="ChangeLoginUser(this)">
<option value="NONE">-- Change User --</option>
<option value="">Windows User</option>
<option value="UserOne">User One</option>
<option value="UserTwo">User Two</option>
</select>
Handle custom selections using javascript ( AppPath link )
function ChangeLoginUser(sel) {
var selectedUser = sel.options[sel.selectedIndex].value;
if (selectedUser == "NONE") return;
$.cookie("LoginUser", selectedUser, { path: AppPath });
location.reload(true);
}
Windows :
protected void Application_AuthenticateRequest(Object sender, EventArgs e)
{
OverrideLoginUser();
}
private void OverrideLoginUser()
{
HttpCookie authCookie = Context.Request.Cookies["LoginUser"];
if (authCookie == null || string.IsNullOrWhiteSpace(authCookie.Value))
return;
if (User != null && User.Username().Equals(authCookie.Value))
return;
Context.User = GetTestUser(authCookie.Value);
}
private WindowsPrincipal GetTestUser(string user)
{
WindowsPrincipal testuser = null;
IntPtr hToken;
if (WinSec.LogonUser(user, "", "ThePassword",
(int)LogonType.LOGON32_LOGON_INTERACTIVE, (int)LogonProvider.LOGON32_PROVIDER_DEFAULT, out hToken))
{
testuser = new WindowsPrincipal(new WindowsIdentity(hToken, "WindowsAuthentication"));
}
if (hToken != IntPtr.Zero) WinSec.CloseHandle(hToken);
}
if (testuser == null)
throw new Exception("Error getting test user");
return testuser;
}
() extension
public static string Username(this IPrincipal user)
{
var name = user.Identity.Name;
name = Regex.Replace(name, ".*\\\\(.*)", "$1", RegexOptions.None);
return name;
}
UserLogon
public class WinSec
{
[DllImport("advapi32.dll", SetLastError = true)]
public static extern bool LogonUser(
string lpszUsername,
string lpszDomain,
string lpszPassword,
int dwLogonType,
int dwLogonProvider,
out IntPtr phToken
);
[DllImport("advapi32.dll", SetLastError = true)]
public extern static bool DuplicateToken(IntPtr ExistingTokenHandle, int SECURITY_IMPERSONATION_LEVEL, out IntPtr DuplicateTokenHandle);
[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool CloseHandle(IntPtr hObject);
}
public enum LogonType
{
LOGON32_LOGON_INTERACTIVE = 2,
LOGON32_LOGON_NETWORK = 3,
LOGON32_LOGON_BATCH = 4,
LOGON32_LOGON_SERVICE = 5,
LOGON32_LOGON_UNLOCK = 7,
LOGON32_LOGON_NETWORK_CLEARTEXT = 8,
LOGON32_LOGON_NEW_CREDENTIALS = 9,
}
public enum LogonProvider
{
LOGON32_PROVIDER_DEFAULT = 0,
LOGON32_PROVIDER_WINNT35 = 1,
LOGON32_PROVIDER_WINNT40 = 2,
LOGON32_PROVIDER_WINNT50 = 3
}
public enum SecurityImpersonationLevel
{
SecurityAnonymous = 0,
SecurityIdentification = 1,
SecurityImpersonation = 2,
SecurityDelegation = 3,
}