From code trying to reset AD user password and using the same password further to login from other services. But AD is not authenticating the user.
In AD we are updating userPassword
, holcimIsRegistered
and userAccountControl
attributes from our code to reset the password.
When we are manually resetting AD user password from ADSI (right click on user -> go to reset password → reset the password) then AD is authenticating the user with the new password. Neither userPassword
nor unicodePwd
attributes are getting updated.
We tried to update unicodePwd
attribute from ADSI and code also but it’s not allowing user to update it’s value, from code we have observed
[LDAP: error code 53 - 0000001F: SvcErr: DSID-031A12D2, problem 5003 (WILL_NOT_PERFORM)]
We compared user details before and resetting password from ADSI and observed that few details are getting
updated (BadLogonCount:0
, badPasswordTime:0
, badPwdCount:0
, lastLogoff:0
, lastLogon:0
, logonCount:0
, Modified
, modifyTimeStamp
, msDS-User-Account-Control-Computed
, PasswordExpired:false
, PasswordLastSet
, uSNChanged
and whenChanged
).
When we tried to modify usnChanged
, msDS-User-Account-Control-Computed
from ADSI then observed that these two attributes were not editable from ADSI and from code it was giving SchemaViolationException
. For passwordExpired
and badLogonCount
attributes , we faced NoSuchAttributeException
while modifying it from code and from ADSI these two attributes were missing.
How else we can make this work?
Advertisement
Answer
To reset the password, you update the unicodePwd
attribute. The documentation tells you about a couple requirements:
- The new password has to be in a specific format: enclosed in double-quotes and then converted to UTF-16 encoding, and
- The connection must be encrypted.
This page has an example of how to do this in Java, which I’ve pasted below. It doesn’t talk about the encryption, but you can use LDAP over SSL (LDAPS), which you can do by using LDAPS://
instead of just LDAP://
. That assumes that the AD server is setup for LDAPS correctly and you don’t have a firewall blocking the LDAPS port (636).
/** * Update User Password in Microsoft Active Directory * @param username * @param password */ public void updateUserPassword(String username, String password) { try { System.out.println("updating password...n"); String quotedPassword = """ + password + """; char unicodePwd[] = quotedPassword.toCharArray(); byte pwdArray[] = new byte[unicodePwd.length * 2]; for (int i = 0; i < unicodePwd.length; i++) { pwdArray[i * 2 + 1] = (byte) (unicodePwd[i] >>> 8); pwdArray[i * 2 + 0] = (byte) (unicodePwd[i] & 0xff); } System.out.print("encoded password: "); for (int i = 0; i < pwdArray.length; i++) { System.out.print(pwdArray[i] + " "); } System.out.println(); ModificationItem[] mods = new ModificationItem[1]; mods[0] = new ModificationItem(DirContext.REPLACE_ATTRIBUTE, new BasicAttribute("UnicodePwd", pwdArray)); ldapContext.modifyAttributes("cn=" + username + BASE_NAME, mods); } catch (Exception e) { System.out.println("update password error: " + e); } }