0
votes

I have set up an ldap authentication using the following configuration. I need user to authenticate using LDAP data store, and in that I have set the pwdMaxFailure to 2.

Authentication is working correctly however every time I login with wrong password I'm getting the following exception instead of Password lock exception. I don't think Spring LDAP is checking the PwdPolicy (Counting the password attempts) while authenticating the user.

ne = (javax.naming.AuthenticationException) javax.naming.AuthenticationException: [LDAP: error code 49 - INVALID_CREDENTIALS: Bind failed: ERR_229 Cannot authenticate user cn=admin,ou=users,o=organisation]

My LDIF file is

dn: cn=admin,ou=users,o=organization objectClass: inetOrgPerson
objectClass: organizationalPerson objectClass: person objectClass: top cn: admin sn: Admin uid: admin userPassword:: e1NTSEF9bEtlTUNzLy9OK1JsV2hCWEM2U2ZZNDh0Lzd0OHBlbjFrdjkxN3c9P Q==
createTimestamp: 20141003000008.689Z creatorsName: 0.9.2342.19200300.100.1.1=admin,2.5.4.11=system entryCSN: 20141020004319.002000Z#000000#001#000000 entryDN: cn=admin,ou=users,o=organization entryParentId: 8204b2df-ff5a-413a-a063-4ac30d35bee4 entryUUID:: N2I1MTFlNjYtMDhjZS00YjA3LWIxYzItNTkyOTI3ZGE3ZTBi modifiersName: 0.9.2342.19200300.100.1.1=admin,2.5.4.11=system modifyTimestamp: 20141020004319.002Z pwdFailureTime: 20141020003207.120Z pwdHistory:: MjAxNDEwMDMwMDAwMDguNjgxWiMxLjMuNi4xLjQuMS4xNDY2LjExNS4xMjEuMS4
0MCM4I1lXUnRhVzQ9 pwdPolicySubentry: cn=default,ou=pwdPolicy,o=organization

dn: cn=default,ou=pwdPolicy,o=organization objectClass: device
objectClass: pwdPolicy objectClass: top cn: default
pwdAttribute: userPassword pwdExpireWarning: 3600 pwdGraceExpire: 1 pwdLockout: TRUE pwdLockoutDuration: 120 pwdMaxAge: 2592000
pwdMaxFailure: 2

And the spring configuration file is as follows

<authentication-manager alias="authenticationManager" xmlns="http://www.springframework.org/schema/security">
  <authentication-provider ref="jdbcProviderManager" />
  <authentication-provider ref="ldapProviderManager" />      
</authentication-manager>

<bean id="jdbcProviderManager" class="au.com.spring.handler.DBLoginAuthentication">
  <property name="userDetailsService" ref="daoAuthenticationProvider" />
</bean>

<bean id="ldapProviderManager" class="au.com.spring.handler.LDAPLoginAuthentication">
  <property name="userDetailsService" ref="ldapAuthenticationProvider" />
</bean>

<bean id="daoAuthenticationProvider" class="org.springframework.security.authentication.dao.DaoAuthenticationProvider">
  <property name="userDetailsService" ref="JdbcUserDetailsManager" />
  <property name="passwordEncoder" ref="encoder" />
</bean>

<bean id="ldapAuthenticationProvider" class="org.springframework.security.ldap.authentication.LdapAuthenticationProvider">
  <constructor-arg>
    <bean class="org.springframework.security.ldap.authentication.BindAuthenticator">
      <constructor-arg ref="contextSource" />
      <property name="userSearch" ref="ldapUserSearch" />
    </bean>
  </constructor-arg>
  <constructor-arg>
    <bean class="au.com.spring.handler.CustomLDAPAuthoritiesPopulator">
      <constructor-arg ref="contextSource" />
      <constructor-arg value="${group.search}" />
      <property name="groupSearchFilter" value="${group.search.filter}" />
      <property name="groupRoleAttribute" value="${group.role.att}" />
      <property name="rolePrefix" value="ROLE_" />
      <property name="searchSubtree" value="true" />
      <property name="convertToUpperCase" value="true" />
    </bean>
  </constructor-arg>
  <property name="hideUserNotFoundExceptions" value="false" />
  <property name="useAuthenticationRequestCredentials" value="true" />
  <property name="userDetailsContextMapper" ref="inetOrgPersonContextMapper" />
</bean>

<bean id="inetOrgPersonContextMapper" class="org.springframework.security.ldap.userdetails.InetOrgPersonContextMapper" />

<bean id="defaultLdapUsernameToDnMapper" class="org.springframework.security.ldap.DefaultLdapUsernameToDnMapper">
  <constructor-arg value="${users.search}" />
  <constructor-arg value="${uid.att}" />
</bean>
<!--<bean id="authenticationSuccessListener" class="prpa.athos.security.listener.AuthenticationSuccessListener" />-->

<!--<bean id="contextSource" class="org.springframework.security.ldap.ppolicy.PasswordPolicyAwareContextSource">-->
<bean id="contextSource" class="org.springframework.security.ldap.ppolicy.PasswordPolicyAwareContextSource">
  <constructor-arg value="ldap://localhost:10389/o=organization" />
  <!--<property name=""/>-->
</bean>
1

1 Answers

1
votes

I'm getting the following exception instead of Password lock exception.

From the LDAP password policy draft 10:

8.1.1. Fail if the account is locked

If the account is locked as specified in Section 7.1, the server fails the operation with an appropriate resultCode (i.e. invalidCredentials (49) in the case of a bind operation, compareFalse (5) in the case of a compare operation, etc.). The server MAY set the error: accountLocked (1) in the passwordPolicyResponse in the controls field of the message.

So the LDAP server is behaving correctly.

I don't think Spring LDAP is checking the PwdPolicy (Counting the password attempts) while authenticating the user

It is the LDAP server that does the checking. Spring would need to provide the extra request control that enables it to see the password-lock status described above. But in any case you never want to disclose to the user why his login failed at login time: that's an information leak. It amounts to telling the attacker that the username is correct, which is never desirable. Let the user enquire why the login failed if he thinks his password is correct, or let him go through the lost-password sequence.