We use Active Directory (AD) and when users are added they get a password set and a flag to enforce “User must change password at next logon” which results in an AD attribute pwdLastSet=0
I have a Java application using Apache LDAP API to authenticate but when I am doing that I get error code 49 INVALID_CREDENTIALS
and no indication to change password.
How can I with Apache LDAP API detect that user has to change password first?
My simple authenticator:
public void authenticate(String uid, String password) { String status = ""; try { LdapConnectionConfig config = new LdapConnectionConfig(); config.setUseSsl(true); config.setLdapHost("activedirectory.domain.net"); config.setLdapPort(636); config.setTrustManagers(new NoVerificationTrustManager()); config.setName(_ldapMgmtUser); config.setCredentials(_ldapMgmtPassword); final DefaultPoolableLdapConnectionFactory factory = new DefaultPoolableLdapConnectionFactory(config); final LdapConnectionPool pool = new LdapConnectionPool(factory); pool.setTestOnBorrow(true); final LdapConnectionTemplate ldapConnectionTemplate = new LdapConnectionTemplate(pool); final PasswordWarning warning = ldapConnectionTemplate.authenticate(_rootDn, "(sAMAccountName=" + uid + ")", SearchScope.SUBTREE, password.toCharArray()); status = "User credentials authenticated"; if (warning != null) { status = status + " n Warning!!" + warning.toString(); } System.out.println(status); } catch (final PasswordException e) { System.err.println("############# PasswordException #############"); status = e.toString(); e.printStackTrace(); } catch (Exception e) { System.err.println("############# Exception #############"); e.printStackTrace(); } finally { } return; }
Advertisement
Answer
I noted that when using LdapConnectionTemplate
and authenticate(...)
(as above) it doesn’t return any useful error codes in the exception and no PasswordWarning
.
Shouldn’t this scenario return a PasswordWarning
?
https://nightlies.apache.org/directory/api/2.0.1/apidocs/org/apache/directory/ldap/client/template/PasswordWarning.html
If I use:
LdapNetworkConnection
and connection.bind(...)
it returns an LdapException
with message
80090308: LdapErr: DSID-0C090453, comment: AcceptSecurityContext error, data 773, v3839
where 773 is what is expected.
It feels like LdapConnectionTemplate has a (few) bug(s).
The full code:
public void authenticateWithBind(String uid, String password) { String status = ""; LdapConnection connection = null; try { LdapConnectionConfig config = new LdapConnectionConfig(); config.setUseSsl(true); config.setLdapHost("activedirectory.domain.net"); config.setLdapPort(636); config.setTrustManagers(new NoVerificationTrustManager()); config.setName(_ldapMgmtUser); config.setCredentials(_ldapMgmtPassword); connection = new LdapNetworkConnection(config); connection.bind(_ldapMgmtUser, _ldapMgmtPassword); EntryCursor cursor = connection.search(_rootDn, "(sAMAccountName=" + uid + ")", SearchScope.SUBTREE, "*"); while (cursor.next()) { Entry entry = cursor.get(); System.out.println("DN: " + entry.getDn()); System.out.println("Attribute: " + entry.get("pwdLastSet")); connection.bind(entry.getDn(), password); status = "User credentials authenticated"; System.out.println(status); } } catch (LdapException e) { System.err.println("############# LdapException #############"); e.printStackTrace(); System.err.println("Error message: " + e.getMessage()); } catch (Exception e) { System.err.println("############# Exception #############"); e.printStackTrace(); System.err.println("Error message: " + e.getMessage()); } finally { closeConnection(connection); } return; }