When I try to change the password of a user via LDAP, in whose AD account the setting is set that the password must be changed at the next login, I get the following error:
cause: javax.naming.AuthenticationException: [LDAP: error code 49 - 80090308: LdapErr: DSID-0C090447, comment: AcceptSecurityContext error, data 773, v3839
Subcode 773 indicates that the user must reset the password, which is exactly what I intend to do right now.
With the following code I can successfully change the password if the above flag is not set:
public void updateUserPassword(String user, String oldPassword,
String newPassword) throws NamingException, LoginException {
try {
InitialDirContext ctx = this.getContext();
String filter = "(&(objectClass=user)(sAMAccountName=" + user + "))";
String baseDn = (String) this.getActiveDirectoryProps().get("baseDN_User");
// Search for user entry
SearchControls ctls = new SearchControls();
ctls.setSearchScope(SearchControls.SUBTREE_SCOPE);
ctls.setReturningObjFlag(true);
String[] returnAttrs = new String[3];
returnAttrs[0] = "cn"; // Common Name
returnAttrs[1] = "displayName";
returnAttrs[2] = "description";
NamingEnumeration<SearchResult> enumSearchResult = ctx.search(baseDn, filter, returnAttrs, ctls);
if (enumSearchResult.hasMore()) {
SearchResult result = enumSearchResult.next();
DirContext userCtx = (DirContext) result.getObject();
// Change the BindUser
ctx.addToEnvironment(Context.SECURITY_PRINCIPAL, userCtx.getNameInNamespace());
ctx.addToEnvironment(Context.SECURITY_CREDENTIALS, oldPassword);
// Update password
Attribute oldattr = new BasicAttribute("unicodePwd", toUnicodeBytes(oldPassword));
Attribute newattr = new BasicAttribute("unicodePwd", toUnicodeBytes(newPassword));
ModificationItem olditem = new ModificationItem(DirContext.REMOVE_ATTRIBUTE, oldattr);
ModificationItem newitem = new ModificationItem(DirContext.ADD_ATTRIBUTE, newattr);
String dn = userCtx.getNameInNamespace();
ctx.modifyAttributes(dn, new ModificationItem[]{olditem, newitem});
}
ctx.close();
} catch (final NamingException nE) {
//
} catch (Exception E) {
//
} finally {
//
}
}
So, do you have any idea what needs to be changed? Or what the reason is that it does not work?
My guess is that you just need to remove these lines:
// Change the BindUser
ctx.addToEnvironment(Context.SECURITY_PRINCIPAL, userCtx.getNameInNamespace());
ctx.addToEnvironment(Context.SECURITY_CREDENTIALS, oldPassword);
You can't authenticate with the old password since it's no longer valid. But you also don't need to bind with the user's own credentials when changing the password, since you have to provide the old password in the request.
These lines may give you trouble too:
Attribute oldattr = new BasicAttribute("unicodePwd", toUnicodeBytes(oldPassword));
Attribute newattr = new BasicAttribute("unicodePwd", toUnicodeBytes(newPassword));
The passwords do have to converted to unicode bytes, but they also have to be enclosed in double quotes too ("
). So you'll probably have to add double quotes before passing it to toUnicodeBytes()
.