SASL - LDAP: error code 49 - 80090303: LdapErr: DSID-0C09054F, comment: The digest-uri does not match any LDAP SPN's registered for this server
I'm trying to update the user password for a user in Microsoft Active Directory with LDAP, using JNDI library over SASL (DIGEST-MD5). And there are a couple of issues that makes the operation fail.
During the authentication phase, I receive the error
Exception: #javax.naming.AuthenticationException: [LDAP: error code 49 - 80090303: LdapErr: DSID-0C09054F, comment: The digest-uri does not match any LDAP SPN's registered for this server., data 0, v2580
I added the required SPN to the DC in AD, and the issue was resolved only for one time, then it came back. When I checked the DC, I found out that the SPN that I have just added has been removed. And this keeps happening every time I add the SPN to the DC!
During the time that the authentication proceeds successfully, the server refuses to update the user's password. I'm trying to update the "unicodePwd" attribute using a "DirContext.REPLACE_ATTRIBUTE" operation (I'm using a domain controller administrator account for the authentication, and trying to update a normal user account).
This is the error I receive "Error:
#javax.naming.OperationNotSupportedException: [LDAP: error code 53 - 0000001F: SvcErr: DSID-031A12D2, problem 5003 (WILL_NOT_PERFORM), data 0 ]; remaining name '<the DN of the user that I was trying to update>'
Another note, when I check the attribute "unicodePwd", it's always unset!! So, the question here "How does the AD authenticate the user? Which attribute holds the user's password?!!
I can use a couple of LDAP clients, and I can update/reset the user's password. I only need to specify the authentication protocol as (SASL) and the operation goes seamlessly =, without having to make any Changes to the AD/SC!
This is the code sample I'm using
// Session variables String adminUsername = "<administrator sAMAccountName value>"; String adminPwd = "<admin password>"; String userDN = "<DN for the user being updated>"; String newPwd = "<The new password for the user being updated>"; String ipAddress = "<AD ip address>"; // LDAP configuration String securityProtocol = "sasl"; String providerURL = "ldap://" + ipAddress; Hashtable<Object, Object> env = new Hashtable<>(); env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); env.put("javax.security.sasl.strength", "high"); env.put("javax.security.sasl.policy.noplaintext", "true"); env.put(Context.PROVIDER_URL, providerURL); env.put(Context.SECURITY_AUTHENTICATION, "DIGEST-MD5"); env.put(Context.SECURITY_PRINCIPAL, adminUsername); env.put(Context.SECURITY_CREDENTIALS, adminPwd); env.put(Context.SECURITY_PROTOCOL, securityProtocol); env.put(Context.REFERRAL, "follow"); // Prepare the modifications list String newQuotedPassword = "\"" + newPwd + "\""; byte newUnicodePassword = newQuotedPassword.getBytes("UTF-16LE"); ModificationItem mods = new ModificationItem; mods = new ModificationItem(DirContext.REPLACE_ATTRIBUTE, new BasicAttribute("unicodePwd", newUnicodePassword)); // Initiate the LDAP connection LdapContext ctx = new InitialLdapContext(env, null); // Modify the password ctx.modifyAttributes(userDN, mods); // Close LDAP connection ctx.close();
Your help is much appreciated.