Register | Login
Sunday, July 20, 2008

Sections
  
About Us
  
Hosting Provided by Server Intellect
Partners
Downloads
  
 WWWCoder.com Resource Directory

Designing an Account Unlock Application
3/20/2004 9:32:55 AM

This article provides some methods and ideas for creating an account self-service application for your intranet portal using ADSI, DCOM, SQL, and ASP.

In this article we are going to try and provide some ideas for you to reduce those calls to the help desk. In this project we created a help desk portal, this portal pretty much has a main page that you can go to download patches, virus definition files, and manage account unlock information. Calls to the help desk for unlocking locked accounts accounted for a large percentage of calls, so in order to streamline the process we created an application that tied in with the intranet user portal. Part of the application design was adding additional fields to the user preferences table called "pin_number", "question", and "answer". As part of the design of the application, we wanted the user to provide a personal identification number, and answer a challenge question that they previously configured in the application. This article is not going to go into every detail of creating the application, but we will provide the ADSI code and some design ideas for creating your own self-service account unlock application.


As mentioned previously, the user had to set up some information in order to be able to use the account unlock application, namely the PIN and challenge question and answer. The intranet portal already had some personalization built into it, so we extended what it provided by adding the appropriate fields for keeping this information. A special Web page was configured that the user could go to and provide this information.



Here they can select from various criteria and provide the information. This will be used to identify the user if they need to unlock their account. This information has to be provided when the user is logged onto the network at their machine (prior to being locked out of course). As mentioned, this information is then saved to the personalization fields of the user's record in the database.


Once this information is saved they are now ready to use the system. The idea behind it is, say they unlock their account, instead of calling the help desk, they can go over to their neighbor's machine and unlock their account. The application will track which account they logged in as, and challenge them for their PIN and answer to their question. In addition, the application checks to see if their account is even locked out in the first place and informs them if it is or not, if it isn't locked out then it prompts them to call the help desk and find out what exactly the problem is or provides additional information. The application also checks to see how many attempts they have made to unlock their account, if the specified threshold is reached, it will inform them that they have tried and failed too many times and to call the Help Desk for assistance. Once an unlock is completed it also logs the event into the help desk application in order to calculate the ROI on the time spent developing the application.


Now let's go through some of the code that we used to achieve this process. As specified they first go to the account unlock page from their neighbor's machine and type in their account information, the application will check to see if their account is currently locked out and presents the information to the user.

Dim strDomain, strUser, oUser 'declare some variable.
CONST UF_LOCKOUT = &H0010 'set some constants for ADSI.
CONST LOCKOUT_COUNT = 3 'how many times to let them try and unlock the account
strDomain = "WinNT://DOMAINNAME" 'specify the domain.
strUser = Request("user") 'set the variable to the username.
'in this next sub we check to see if they reached the threshold
'for failed attempts to unlock their account.

Sub Main
If Session("wrongquestion") > LOCKOUT_COUNT Then
sFrom = strUser
sFromAddress = strUser & "@santry.com"
sTo = "Webmaster@somecompany.com"
sSubject = "Unlock Limit Reached: " & strUser
sBodyText = "The following account reached the unlock attempts limit" _
" via the intranet: " & strUser & vbcrlf & _
"Logged on User: " & Request.ServerVariables("LOGON_USER") & vbcrlf & _
"Time of incident: " & Now()
x = SendMail(sFrom, sFromAddress, sTo, sToName, sSubject, sBodyText)
Response.Write "You have reached the limit set for unlock attempts, " _
please contact the Help Desk for more information."
Else
Select Case Request("action")
Case "unlock"
CheckforUnlock
Case "logon"
If GetUserADSI Then
DisplayStatus
Else
Response.Write "There was a problem " _
"accessing this account: " & strUser & _
", please ensure that you entered the correct account."
End If
Case Else
Logon
End Select
End If
End Sub



In the previous routine, we first checked to see if the lockout threshold was reached, if it was we send a message to the Webmaster (could be an admin or whoever), and addition carbon copy the message to the user. We also provide them with information on who was the logged on user at the time, and the time of the attempt. If we haven't met the threshold we check an action parameter. This parameter is either we're trying to get information on the account or actually try to unlock the account. If we can't obtain the account information, then we present an error to the user letting them know. If the user is just logging onto the system then we check to make sure they exist in our domain by using the following routine:

Function GetUserADSI
GetUserADSI = False
On Error Resume Next
Set oUser = GetObject(strDomain & "/" & strUser)
If Err <> 0 Then
GetUserADSI = False
Else
GetUserADSI = True
End If
End Function




GetUserADSI checks to see if the account is in our domain, if it isn't then it will raise an error, we'll catch the error and return false if the error is there, if it isn't then we'll return true. If the return is true, then we'll go back to the Main method where you'll see we call another routine called DisplayStatus. What DisplayStatus does is check the domain to see if their account is actually locked out or not.

Sub DisplayStatus
Response.Write "Information for account: " & strUser & _
GoUser.FullName & _
oUser.Description & _
"Account Status: " & GetUserFlags(oUser)
End Sub
'check to see if the account is locked out and present to the user.
Function GetUserFlags(UserObj)
Dim Flags, strTemp
Flags = UserObj.Get("UserFlags")
If (Flags and UF_LOCKOUT) <> 0 Then
strTemp = "Account Locked Out! " & _
DisplayChallange
Else
strTemp = "Account is not locked out, if " _
"you are having problems accessing the network " & _
"please contact the help desk."
End If
GetUserFlags = strTemp
End Function




In this next method we're going to check their entered information against what the user previously saved in the database along with their preferences. If we have a match then we'll unlock the account and log an entry into the help desk system.

Sub CheckForUnlock
Dim adoconn, rs, SQLQ, strTemp, intQuestion
Set adoconn = Server.CreateObject("ADODB.Connection")
adoconn.Open Application("Connection_String")
'now check the portal database, where we keep the user preferences
'see if the information matches that that is in the database.
'also you will see a call to the base64method, this is to do minor
'encryption in the database so the information is not readily viewable
'by the DBA.
SQLQ = "SELECT AccountQuestion FROM MEMBERS WHERE Account LIKE '%\" & strUser & "'" & _
" AND AccountAnswer = '" & base64Encode(Replace(Request("answer"), "'", "''")) & "'" & _
" AND PIN = '" & base64Encode(Request("pin")) & "'"
Set rs = adoconn.Execute(SQLQ)
If Not rs.EOF Then
'then unlock the account.
If UnlockUser Then
'send email, unlock account, write event to help desk tracking system.
sFrom = strUser
sFromAddress = strUser & "@santry.com"
sTo = "Webmaster@santry.com"
sSubject = "Account Unlocked: " & strUser
sBodyText = "The following account was unlocked via the " _
"intranet self-service: " & strUser & vbcrlf & _
"Logged on User: " & Request.ServerVariables("LOGON_USER") & vbcrlf & _
"Time of incident: " & Now()
x = SendMail(sFrom, sFromAddress, sTo, sToName, sSubject, sBodyText)
'log to the help desk system.
Response.Write "Account unlocked and notification was sent to the help desk " _
"notifying of the change. Changes to your account can " _
"take up to 20 minutes to be applied." & _
" For reference refer to Help Desk Ticket #: " & _
CreateHelpDeskTicket(strUser, "Machine of: " & Request.ServerVariables("LOGON_USER"))
If Err.number <> 0 Then
Err.Clear
End If
Else
Response.Write "An error occured trying to unlock your account, please contact the Help Desk."
End If
Else
'whatever checking you want here.
Session("wrongquestion") = Session("wrongquestion") + 1
Response.Write "You have entered in the wrong answer and/or PIN " & Session("wrongquestion") & _
" time(s) during this session."
End If
rs.Close
Set rs = Nothing
adoconn.Close
Set adoconn = Nothing
End Sub




You'll notice in the above routine that we made a call to the Unlock user function, which returns a boolean value based on whether or not it was successful unlocking the account. This function makes a call to a DCOM object that is running under a privileged account. This object will then perform the account unlock for us.

Function UnlockUser
On Error Resume Next
UnlockUser = False
Dim strAccount, objUnlock, blnUnlock
strAccount = strDomain & "/" & strUser
Set objUnlock = Server.CreateObject("NTAdmin.Accounts")
blnUnlock = objUnlock.UnlockUser(strAccount)
Set objUnlock = Nothing
If Err = 0 Then
UnlockUser = True
Else
UnlockUser = False
End If
End Function




The DCOM object basically contains one function and that is to unlock the account. The primary reason it runs in DCOM is so we can do impersonation with the object and have it run under an account with account operator privileges. To create the object start a VB project and add a class file called accounts to the project. Inside this class just place the following code.

Const UF_LOCKOUT = &H10
Public Function UnlockUser(inAccount As Variant) As Boolean
On Error Resume Next
Dim oUser As Variant
UnlockUser = False
Set oUser = GetObject(inAccount)
Flags = oUser.Get("UserFlags")
oUser.Put "UserFlags", Flags Xor UF_LOCKOUT
oUser.SetInfo
Set oUser = Nothing
If Err.Number = 0 Then
UnlockUser = True
Else
UnlockUser = False
End If
End Function




The object will return a boolean value based on whether or not the object was successful in unlocking the account.


This article should provide you with enough information to develop your own account unlock tool for your intranet portal. You can extend this application by providing functions like password changes and any other method that ADSI will provide. By logging the actions to your help desk system you will be able to provide an actual ROI to your managers for the development work preformed.


 

By: Patrick Santry, Microsoft MVP (ASP/ASP.NET), developer of this site, author of books on Web technologies, and member of the DotNetNuke core development team. If you're interested in the services provided by Patrick, visit his company Website at Santry.com.

Related Articles
   Related Document Obtaining Active Directory User Information Using System.DirectoryServices
   Related Document Introduction to Windows and Active Directory Services Interface (ADSI)


Page Options:
format for printing  Format for Printer
email article  Email Page
add to your favorites   Add to Favorites
How would you rate the quality of this content?
Poor - - Excellent
Comments?
Overall Rating:
Comments Left:
Left on 11/21/2007 7:28:21 PM by Anonymous
Comments: If anyone has successfully implemented this and would be willing to share the info, please post it here in the comments.
Left on 4/17/2006 12:38:28 AM by Anonymous
Comments: good
No ratings available.
Left on 2/3/2005 4:54:28 PM by Anonymous
Comments: It has some very usefull information for the ADSI.. I agree that there are a few too many gaps for understanding the DCOM accounts.class and how to implement this.  Since this is an important factor in making it useful, I'd think more information would be useful.
Left on 6/24/2004 11:24:22 AM by Anonymous
Comments: Very good article. The last page gets a little confusing. How does one create and run the program for dom?
No ratings available.
  

 Latest Articles
  

 Latest News
  

 

Spotlight
Syndication

 


 


Digg This
 


DotNetNuke Platinum Benefactor

  
 

 Terms Of Use | Privacy Statement
 Copyright 2008 - Santry Technology Solutions, Box 172, Girard, PA 16417, (814) 774-0970