0
votes

I have a web form that uses AD to authenticate users. I want to be able to authenticate users with expired password, and redirect them to the password change page after authentication.

if for instance, a site admin reset a users password, I use the method below, to make the user reset their password on next logon.

Public Shared Sub ForceUserToResetPassword(ByVal LDAP_URI As String, ByVal UserName As String, ByVal       Auth_UserName As String, ByVal Auth_Password As String)
    Dim LDAPEntry As DirectoryEntry = Nothing
    Try
        LDAPEntry = New DirectoryEntry(LDAP_URI, Auth_UserName, Auth_Password, AuthenticationTypes.Secure)
        Dim LDAPSearch As New DirectorySearcher()
        LDAPSearch.SearchRoot = LDAPEntry
        LDAPSearch.Filter = "(&(objectClass=user)(sAMAccountName=" & UserName & "))"


        LDAPSearch.SearchScope = SearchScope.Subtree
        Dim results As SearchResult = LDAPSearch.FindOne()
        If Not (results Is Nothing) Then
            LDAPEntry = New DirectoryEntry(results.Path, Auth_UserName, Auth_Password, AuthenticationTypes.Secure)
        End If

        LDAPAccess.SetProperty(LDAPEntry, "pwdLastSet", 0)
        LDAPEntry.CommitChanges()

    Catch ex As Exception

    End Try
End Sub

Doing this makes the user's password expire. If the user try to logon with their new password the authentication fails with "Logon failure: unknown username or bad password".

This is my auth. method:

Public Shared Function AuthADuser(ByVal LDAP_URI As String, ByVal UserName As String, ByVal password As String, ByVal Auth_UserName As String, ByVal Auth_Password As String) As Boolean
    Dim IsAuth As Boolean = False
    Dim LDAPEntry As DirectoryEntry = Nothing
    Try
        LDAPEntry = New DirectoryEntry(LDAP_URI, UserName, password, AuthenticationTypes.Secure)
        Dim tmp As [Object] = LDAPEntry.NativeObject
        IsAuth = True
    Catch ex As Exception
        LDAPEntry.Dispose()
        If ex.Message.StartsWith("The server is not operational") Then
            IsAuth = False
        ElseIf ex.Message.StartsWith("Logon failure:") Then
            Throw New ApplicationException("The Username and password combination are not valid to enter the system.")
        End If
    Finally
        LDAPEntry.Close()
    End Try
    Return IsAuth
End Function

Is there a way around this?

Thanks for your help.

1
This seems like a wasted effort. If their password is expired and needs to be changed, then logging in to the domain will prompt for a password change long before they open their web browser and access your intranet site.HardCode

1 Answers

1
votes

In my understanding, if a user is required to Change his Password at Next Logon (User's password has expired) Active-Directory will not allow us to use LDAP to determine if his password is invalid or not. This is due to the fact that a user must change password. I found here the following solution :

To determine if password is expired, you may call Win32:LogonUser(), and check the windows error code for the following 2 constants:

ERROR_PASSWORD_MUST_CHANGE = 1907
ERROR_PASSWORD_EXPIRED = 1330

I have a non official answer. As administrator you put pwdLastSet to -1 for the user where pwdLastSet is set to 0. The effect of this is to make Active-Directory believe that the password has just been changed. Then, you check the password with your AuthADuser method. Then you put back pwdLastSet to 0. I do not test it, but just imagine it, it's not so clean on the security point of view (in France we call that "bricolage").

Just tell me if it works ?

I hope it helps;

JP