Using ASP.Net to Delegate Domain Password Resets to Business Managers

Overview

This article shows how to develop a simple ASP.NET-based application for the purpose of providing non-IT management staff (in other words a marketing team leader) the ability to reset a delegate's Windows domain account password. The purpose of such an application is to reduce the number of service desk tickets relating to account password resets and enhance the productivity of an end user by forestalling the superfluous and prolonged delays that often occur during the traditional password reset process.

Logging

You will notice that I do not specify the logging of the password reset information in this article. Whereas it is incredibly important to log who is resetting what, or who is attempting to reset what, I believe that explaining the logging process in this article would have only served to distract the reader from the actual password reset task. Since logging is relatively simple and due to the fact that many businesses log information in various ways, I chose to omit that procedure from the article.

Language guide

When I refer to the delegate, I am referring to the user that requires their password to be reset. When I refer to the manager, I am referring to the manager that is listed against the delegates account in the Active Directory. When I refer to the user, I am referring to the user that is attempting to reset the delegate's password via the web form.

Setup guide

Our first step is to edit our Web.config file to utilize Windows authentication.

  1. <authentication mode ="Windows" />  
  2. lt;authorization>  
  3.   <deny users="?"/> <!--Prevent Anonymous Authorization-->  
  4. lt;/authorization  

Once the Web.config file has been edited, we will need to add some components, three text boxes and two buttons, to our web form. The following image details how I have chosen to name these components on my form.

Now that the proper components have been added to our form, we will need to add a reference to the System.DirectoryServices.dll. We do this by adding a reference via Visual Studio's Reference Manager and by adding the following using statement to our code:

  1. using System.DirectoryServices;  

We are now ready to start work on the password reset (btnReset) itself. Since we will need to compare the Delegate's Manager's username against the name of the User who is requesting the password reset, it is essential that we capture the username of the User requesting the password reset. We are able to do this with the following lines of code:

  1. //Get User's Username  
  2. string strRawUser = HttpContext.Current.User.Identity.Name;  
  3.   
  4. //Remove Domain Name From User's Username ('TEST\bgates' will become 'bgates')  
  5. string[] strSplitUser = strRawUser.Split(new char[] { '\\' });  
  6. string strUsername = strSplitUser[1];  

Once this username has been captured, we need to have something to compare it to. To gather the Delegate's Manager's username from the Active Directory, we need to perform two separate searches. The first will capture the Manager's distinguished name from the Delegate's Active Directory user profile and the second will resolve the Manager's username from this distinguished name.

  1. //Get Manager's Distinguished Name From Active Directory  
  2. string strConn = "LDAP://dc=test,dc=local";  
  3. DirectorySearcher dSearch = new DirectorySearcher(strConn);  
  4. dSearch.Filter = "(sAMAccountName=" + txtUsername.Text + ")";  
  5. SearchResult sResult = dSearch.FindOne();  
  6. DirectoryEntry dResult = sResult.GetDirectoryEntry();  
  7.   
  8. string strRawManager = dResult.Properties["manager"][0].ToString();  
  9.   
  10. //Get Manager's Username From Distinguished Name  
  11. DirectorySearcher diSearch = new DirectorySearcher(strConn);  
  12. diSearch.Filter = "(distinguishedName=" + strRawManager + ")";  
  13. SearchResult seResult = diSearch.FindOne();  
  14. DirectoryEntry diResult = seResult.GetDirectoryEntry();  
  15.   
  16. String strManager = diResult.Properties["sAMAccountName"][0].ToString();  

We now need to compare the user's username to the manager's username. In the event that the user's username does in fact match the manager's username (meaning that the user is the manager), we should proceed to check the delegate's account status, since we do not wish to allow managers to reset passwords for deactivated accounts.

  1. //If User's Username Is The Same As Manager's Username  
  2. if (strUsername == strManager)  
  3. {  
  4.     //Get Delegate Account Status  
  5.     int intFlags = (int)dResult.Properties["userAccountControl"].Value;  

If the delegate's account has been disabled, we will display an error stating as such.

  1. //If Delegate's Account Is Disabled  
  2. if (intFlags == 514)   
  3. {  
  4.     //Show Error Message  
  5.     string strDisabled = "Selected Account Disabled. Unable To Reset Password.";  
  6.     ClientScript.RegisterStartupScript(this.GetType(), "myalert""alert('" + strDisabled + "');"true);  
  7. }  

However, if the delegate's account is enabled, we are able to proceed to the next step of the password reset process. In this next step, we will need to confirm that the user has correctly entered the password on the form and that the txtPassword field matches the txtConfirmPW field.

If the txtPassword field matches the txtConfirmPW field, we should reset the delegate's password, confirm that the account is unlocked and ensure that the delegate is prompted to reset their password on the first logon. We also display a success message to the user.

  1. else  
  2. {  
  3.     //If Password And Confirmation Fields Match (On Form)  
  4.     string strPassword = txtPassword.Text;  
  5.     string strConfirmPW = txtConfirm.Text;  
  6.   
  7.     if (strPassword == strConfirmPW)  
  8.     {  
  9.         //Reset Delegate's Password, Unlock Account, Ensure User Has To Reset Password On Next Login  
  10.         dResult.Invoke("SetPassword", strPassword);  
  11.         dResult.Properties["LockOutTime"].Value = 0;  
  12.         dResult.Properties["pwdLastSet"].Value = 0;  
  13.   
  14.         //Commit Changes  
  15.         dResult.CommitChanges();  
  16.   
  17.         //Show Success Message  
  18.         string strSuccess = "Congratulations! Password Reset Successfully.";  
  19.         ClientScript.RegisterStartupScript(this.GetType(), "myalert""alert('" + strSuccess + "');"true);  
  20. }  

If the txtPassword field does not match the txtConfirmPW field however, we will need to display an error asking the user to check the data on the form.

  1. //If Password Does Not Match Confirmation Field (On Form)  
  2. else  
  3. {  
  4.     //Show Error Message  
  5.     string strNoMatch = "Entered Passwords Do Not Match. Please Try Again.";  
  6.     ClientScript.RegisterStartupScript(this.GetType(), "myalert""alert('" + strNoMatch + "');"true);  
  7. }  

The final part of our password reset button's code should address what happens if the user's username does not match the manager's username. In the event that these two usernames do not match, we simply need to display an error message to the user.

  1. //If User's Username Does Not Match Manager's Username  
  2. else  
  3. {  
  4.    //Show Failure Message  
  5.    string strFailure = "You Do Not Have Permission To Perform This Action.";  
  6.    ClientScript.RegisterStartupScript(this.GetType(), "myalert""alert('" + strFailure + "');"true);  
  7. }  

The final part of our code refers to that pesky Clear Form button (btnClear). You are able to clear the form in a number of ways, however I find the simplest way is to simply reset the web form.

  1. //Clear Form  
  2. protected void btnClear_Click(object sender, EventArgs e)  
  3. {  
  4.    //Refresh Form  
  5.    Response.Redirect(Request.RawUrl);  
  6. }  

Full Code

  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Web;  
  5. using System.Web.UI;  
  6. using System.Web.UI.WebControls;  
  7.   
  8. using System.DirectoryServices;  
  9.   
  10. namespace ADReset  
  11. {  
  12.     public partial class WebForm1 : System.Web.UI.Page  
  13.     {  
  14.           
  15.         //Reset Password  
  16.         protected void btnReset_Click(object sender, EventArgs e)  
  17.         {  
  18.             //Get User's Username  
  19.             string strRawUser = HttpContext.Current.User.Identity.Name;  
  20.   
  21.             //Remove Domain Name From User's Username ('TEST\bgates' will become 'bgates')  
  22.             string[] strSplitUser = strRawUser.Split(new char[] { '\\' });  
  23.             string strUsername = strSplitUser[1];  
  24.   
  25.             //Get Manager's Distinguished Name From Active Directory  
  26.             string strConn = "LDAP://dc=test,dc=local";  
  27.             DirectorySearcher dSearch = new DirectorySearcher(strConn);  
  28.             dSearch.Filter = "(sAMAccountName=" + txtUsername.Text + ")";  
  29.             SearchResult sResult = dSearch.FindOne();  
  30.             DirectoryEntry dResult = sResult.GetDirectoryEntry();  
  31.   
  32.             string strRawManager = dResult.Properties["manager"][0].ToString();  
  33.   
  34.             //Get Manager's Username From Distinguished Name  
  35.             DirectorySearcher diSearch = new DirectorySearcher(strConn);  
  36.             diSearch.Filter = "(distinguishedName=" + strRawManager + ")";  
  37.             SearchResult seResult = diSearch.FindOne();  
  38.             DirectoryEntry diResult = seResult.GetDirectoryEntry();  
  39.   
  40.             string strManager = diResult.Properties["sAMAccountName"][0].ToString();  
  41.   
  42.             //If User's Username Is The Same As Manager's Username  
  43.             if (strUsername == strManager)  
  44.             {  
  45.                 //Get Delegate Account Status  
  46.                 int intFlags = (int)dResult.Properties["userAccountControl"].Value;  
  47.   
  48.                 //If Delegate's Account Is Disabled  
  49.                 if (intFlags == 514)   
  50.                 {  
  51.                     //Show Error Message  
  52.                     string strDisabled = "Selected Account Disabled. Unable To Reset Password.";  
  53.                     ClientScript.RegisterStartupScript(this.GetType(), "myalert""alert('" + strDisabled + "');"true);  
  54.                 }  
  55.   
  56.                 else  
  57.                 {  
  58.                     //If Password And Confirmation Fields Match (On Form)  
  59.                     string strPassword = txtPassword.Text;  
  60.                     string strConfirmPW = txtConfirm.Text;  
  61.   
  62.                     if (strPassword == strConfirmPW)  
  63.                     {  
  64.                         //Reset Delegate's Password, Unlock Account, Ensure User Has To Reset Password On Next Login  
  65.                         dResult.Invoke("SetPassword", strPassword);  
  66.                         dResult.Properties["LockOutTime"].Value = 0;  
  67.                         dResult.Properties["pwdLastSet"].Value = 0;  
  68.   
  69.                         //Commit Changes  
  70.                         dResult.CommitChanges();  
  71.   
  72.                         //Show Success Message  
  73.                         string strSuccess = "Congratulations! Password Reset Successfully.";  
  74.                         ClientScript.RegisterStartupScript(this.GetType(), "myalert""alert('" + strSuccess + "');"true);  
  75.                     }  
  76.   
  77.                     //If Password Does Not Match Confirmation Field (On Form)  
  78.                     else  
  79.                     {  
  80.                         //Show Error Message  
  81.                         string strNoMatch = "Entered Passwords Do Not Match. Please Try Again.";  
  82.                         ClientScript.RegisterStartupScript(this.GetType(), "myalert""alert('" + strNoMatch + "');"true);  
  83.                     }  
  84.                 }  
  85.             }  
  86.   
  87.             //If User's Username Does Not Match Manager's Username  
  88.             else  
  89.             {  
  90.                 //Show Failure Message  
  91.                 string strFailure = "You Do Not Have Permission To Perform This Action.";  
  92.                 ClientScript.RegisterStartupScript(this.GetType(), "myalert""alert('" + strFailure + "');"true);  
  93.             }  
  94.         }  
  95.   
  96.         //Clear Form  
  97.         protected void btnClear_Click(object sender, EventArgs e)  
  98.         {  
  99.             //Refresh Form  
  100.             Response.Redirect(Request.RawUrl);  
  101.         }  
  102.     }  
  103. }  

X

Build smarter apps with Machine Learning, Bots, Cognitive Services - Start free.

Start Learning Now