Please help!
I am new to the .NET web application development. I have used the code from the link below to create a basic login page in front of the Microsoft Live Single Sing On.
http://support.microsoft.com/default.aspx/kb/326340
I managed to combine the two together (LiveSSO w/ Forms Authentication) turning off the Integrated Authentication in IIS from the SSO setup. All works as expected if the user successfully authenticates with AD.
THE PROBLEM that I am having is that when the user failes to authenticate it only returns: “Error authenticating user. Logon failure: unknown user name or bad password”. This message appears also when the user is set to change the password at next logon. What I want it to do is to read the error code of exactly why it failed so I can setup a redirect to a password reset page (i.e. if error is “User flag is set to change pswd” etc.etc.)
From the page linked above you can see the VB code of LdapAuthentication.vb which does the trick of authenticating the accounts or returning the error message if the login fails.
The part that returns the “Error authenticating user. Logon failure: unknown user name or bad password.” Is handled by this subroutine:
- Catch ex As Exception
- Throw New Exception(“Error authenticating user. ” & ex.Message)
- End Try
That’s what I have been trying to customize to see how it can return a specific code based on the user account AD flags, instead of the generic message.
Does anyone have any clue or idea how I can accomplish that? Any help would be greatly appreciated. Thanks in advance!
I’m pretty sure you are already seeing the most detailed error that AD is going to throw at you given the technique being used.
When a login fails, AD is deliberately a little vague as to the exact reason. This prevents hackers from knowing which part of the login credentials they may have gotten right or wrong, thus denying them the ability to tailor their next attempt based on information gleaned from their earlier failures.
To do what you are wanting to do, you will need to have different code that connects to AD using a service account setup for the application. This code would then need to take the credentials the user supplied, find the relevant directory entry for that user, then read the information about the account reset flags and such.
Once that’s done, and everything is OK, you’d then pass control off the the actual login code and attempt the login for the user. If everything weren’t OK, you’d redirect the user without attempting to log them in with their own credentials.
[Update]
Here is a quick code example of how you “might” go about doing something like this:
VB is not my native language of choice, so this is an untested conversion from a quick example I mocked up in C#. No guarantees that this will work exactly as is.
You will need to import the System.DirectoryServices.AccountManagement namespace to use this.
The PrincipalContext constructor shown in this example is the very basic version, and will only work if your web application itself is using a service account that has the necessary access to your active directory to read from it. If not, look at the overloads for the constructor and use the one that lets you supply the domain user and password credentials used to build the PrincipalContext.
The major point of the function here is to check the LastPasswordSet value AND the PasswordNeverExpires value from AD for the user account that is about to attempt a login. If both of these are unset, then the user’s account will require them to change the password before they login.
So you’d just make a call to this function BEFORE you try authenticating the user. If the function returns true then the user cannot login until they change the password and you should redirect the user to a change password page.