August 25, 2010

Sign in as Different User in ASP.NET Applications

"Sign in as Different User" is one of a cool feautures in SharePoint and we can implement that in ASP.NET Applications too.
Below are the steps:
0. Default.aspx
1. Forms/frmHome.aspx
2. Forms/frmAccessDenied.aspx

IIS requires Default.aspx to redirect to Forms/frmHome.aspx

---------------------------frmHome.aspx-----------------------------
Keep a Link Button with Sign in as Different User as text

-----------------------frmHome.aspx code------------------------------

----------------------page load----------------------------------

protected void Page_Load(object sender, EventArgs e)
{
Control cause = GetPostBackControl(Page);
string sUser = "";
if (Request.LogonUserIdentity.IsAuthenticated == true)
{
if (!IsPostBack == true)
{
sUser = Request.LogonUserIdentity.Name;
sUser = sUser.Remove(0, sUser.IndexOf("\\") + 1);
txtLoginID.Text = sUser.ToUpper();
GetUserId();
FillRoles();
txtLoginID.Focus();
this.DisablePageCaching();
}
else if (cause.ClientID == "LinkButton1")
{
sUser = Request.LogonUserIdentity.Name;
sUser = sUser.Remove(0, sUser.IndexOf("\\") + 1);
txtLoginID.Text = sUser.ToUpper();
GetUserId();
FillRoles();
txtLoginID.Focus();
this.DisablePageCaching();
}
else
{
sUser = Request.LogonUserIdentity.Name;
sUser = sUser.Remove(0, sUser.IndexOf("\\") + 1);
txtLoginID.Text = sUser.ToUpper();
}
}
}

-----------------------------On CLick----------------------------------

protected void LinkButton1_Click(object sender, EventArgs e)
{
Response.Redirect("~/Forms/AccessDenied.aspx");
}

------------------------------DisablePageCaching---------------------------

public void DisablePageCaching()
{
Response.Expires = 0;
Response.Cache.SetNoStore();
Response.AppendHeader("Pragma", "no-cache");
}

--------------------Get the control which does post back----------------

public static Control GetPostBackControl(Page page)
{
Control postbackControlInstance = null;
string postbackControlName =
page.Request.Params.Get("__EVENTTARGET");
if (postbackControlName !=
null && postbackControlName != string.Empty)
{
postbackControlInstance =
page.FindControl(postbackControlName);
}
else
{
// handle the Button control postbacks

for (int i = 0; i < page.Request.Form.Keys.Count; i++) { postbackControlInstance = page.FindControl(page.Request.Form.Keys[i]); if (postbackControlInstance is System.Web.UI.WebControls.Button) { return postbackControlInstance; } } } // handle the ImageButton postbacks if (postbackControlInstance == null) { for (int i = 0; i < page.Request.Form.Count; i++) { if ((page.Request.Form.Keys[i].EndsWith(".x")) || (page.Request.Form.Keys[i].EndsWith(".y"))) { postbackControlInstance = page.FindControl(page.Request.Form.Keys[i].Substring (0,page.Request.Form.Keys[i].Length - 2)); return postbackControlInstance; } } } return postbackControlInstance; } --------------frmAccessDenied.aspx.cs-------------- using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.UI; using System.Web.UI.WebControls; public partial class Forms_AccessDenied : System.Web.UI.Page { private int _authenticationAttempts = 0; public int AuthenticationAttempts { get { if (!string.IsNullOrEmpty(string.Format("{0}", Session["AuthenticationAttempts"]))) { int.TryParse(Session["AuthenticationAttempts"].ToString(), out _authenticationAttempts); } return _authenticationAttempts; } set { _authenticationAttempts = value; Session["AuthenticationAttempts"] = _authenticationAttempts; } } private string _currentUser = string.Empty; public string CurrentUser { get { _currentUser = Request.LogonUserIdentity.Name; Session["CurrentUser"] = _currentUser; return _currentUser; } set { _currentUser = value; Session["CurrentUser"] = _currentUser; } } private string _previousUser = string.Empty; public string PreviousUser { get { _previousUser = string.Format("{0}", Session["PreviousUser"]); return _previousUser; } set { _previousUser = value; Session["PreviousUser"] = _previousUser; } } ///
/// This event fires on every page load
///

/// /// protected void Page_Load(object sender, EventArgs e)
{
// Make sure the browser does not cache this page
this.DisablePageCaching();

// Increase authentication attempts
this.AuthenticationAttempts = this.AuthenticationAttempts + 1;

if (this.AuthenticationAttempts == 1)
{
// Change previous user to current user
this.PreviousUser = this.CurrentUser;

// Send the first 401 response
this.Send401();
}
else
{
// When a browser is set to "automaticaly sign in with current credentials", we have to send two 401 responses to let the browser re-authenticate itself.
// I don't know how to determine if a browser is set to "automaticaly sign in with current credentials", so two 401 responses are always send when the user
// does not switch accounts. In Micrososft Office sharepoint the user has to supply the credentials 3 times, when the user does not switch accounts,
// so it think this is not a problem.
if (this.AuthenticationAttempts == 2 && this.CurrentUser.Equals(this.PreviousUser))
{
// Send the second 401 response
this.Send401();
}
else
{
// Clear the session of the current user. This will clear all sessions objects including the "AuthenticationAttempts"
Session.Abandon();
Session.Clear();

// Redirect back to the main page
Response.Redirect("~/Forms/frmHome.aspx");
}
}
}

///
/// Make sure the browser does not cache this page
///

public void DisablePageCaching()
{
Response.Expires = 0;
Response.Cache.SetNoStore();
Response.AppendHeader("Pragma", "no-cache");
}
///
/// Send a 401 response
///

public void Send401()
{
// Create a 401 response, the browser will show the log-in dialogbox, asking the user to supply new credentials, // if browser is not set to "automaticaly sign in with current credentials"
Response.Buffer = true;
Response.StatusCode = 401;
Response.StatusDescription = "Unauthorized";

// A authentication header must be supplied. This header can be changed to Negotiate when using keberos authentication
Response.AddHeader("WWW-Authenticate", "NTLM");

// Send the 401 response
Response.End();
}
}

-----------------------IIS 7 Settings -- IMPT --------------------------

1. Once you publish the website to wwwroot
2. Under Default Site in IIS, right click the folder and convert it to application
3. Disable Anaonymous authentication and enable only windows authentication
4. Check Permissions under Secuirty Tab of Virtual Directory if users have access or not.

----------------------------Web.Config---------------------------------

<authentication mode="Windows"/>
<identity impersonate="false" />
<authorization>
<allow users="?"/>
</authorization>

--------------------------Happy Coding ----------------------------------

2 comments:

Francisco said...

its a little confusing going through the code like this, could you please post the source code in a zip file?

thanks.

Sree said...

Hey Pepe, I dont know.. in edit view the code loks good but once i post the code gets very close and messy, I will post the zip file sometime soon.

SonarQube with Jenkins Setup using Docker Images

https://funnelgarden.com/sonarqube-jenkins-docker/  https://medium.com/@hakdogan/an-end-to-end-tutorial-to-continuous-integration-and-con...