implementing spring security with ldap and password encoding

6.1k views Asked by At

i have implemented spring security login successfully with ldap and plaintext. now im switching to sha-256 for the password hash in ldap. i have added password-encoder in applicationContext-security.xml. however, i have not been able to authenticate successfully with spring security. i receives "you have entered an invalid username or password!"

here are my codes:

applicationContext-security.xml

  <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:security="http://www.springframework.org/schema/security"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
        http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd">

        <security:http auto-config="true" use-expressions="true" access-denied-page="/user/denied" >
            <security:form-login
                    login-page="/login" 
                    authentication-failure-url="/login?error=true" 
                    default-target-url="/admin/user"/>
            <security:logout invalidate-session="true" 
                    logout-success-url="/login" 
                    logout-url="/j_spring_security_logout"/>
        </security:http>
        <security:authentication-manager>
            <security:ldap-authentication-provider user-search-filter="uid={0}" user-search-base="ou=Users">
             <security:password-compare>
                 <security:password-encoder hash="sha-256" />
             </security:password-compare>
           </security:ldap-authentication-provider>
        </security:authentication-manager>

        <bean id="contextSource" class="org.springframework.security.ldap.DefaultSpringSecurityContextSource">
            <constructor-arg value="ldap://192.168.1.100:389/dc=openLDAP" />
            <property name="userDn" value="cn=admin,dc=openLDAP" />
            <property name="password" value="password" />
        </bean>
</beans>

login controller:

@RequestMapping(value="/login", method=RequestMethod.GET)
public String login(@RequestParam(value="error", required=false) boolean error, ModelMap model, HttpServletRequest request) {
   HttpSession session = request.getSession();
   if(session.getAttribute("SPRING_SECURITY_CONTEXT" != null) {
      return "redirect:/home";
   }

   if(error) {
      model.put("error", "you have entered an invalid username or password!");
   }
   else {
      model.put("error", "");
   }

   return "login";
}

login view:

<form action="j_spring_security_check" method="post" >
   username: <input id="j_username" name="j_username" type="text" />
   password: <input id="j_password" name="j_password" type="password" />
</form>
1

There are 1 answers

3
Ralf On BEST ANSWER

I think your problem is that you are hashing the passowrd on the client side (spring-security) and then OpenLDAP hashes that string again and then compares the result with the stored password hash. One the two combinations should work:

  1. Configure a hashing algorithm in spring-security and store the password hash as plain text password type in OpenLDAP -> The hashed password is sent to your LDAP and compared against the stored hashed password.
  2. Do not configure hashing in spring-security and store the password as a hashed password type in OpenLDAP (like you did as per your comment) -> The plain text password is sent to your LDAP, hashed by the LDAP server and then compared against the stored password hash.

I recommend 2) in combination with an SSL encrypted connection to your LDAP server to protect the plain text password in transit. If you go for 2) you can easily enable salting of your password hashes by using the SMD5 password type. 1) has the downside that each client is required to support the chosen hash function.