Results 1 to 7 of 7

Thread: Authentication Failing after password change

  1. #1
    Join Date
    Feb 2009
    Posts
    7

    Unhappy Authentication Failing after password change

    Spring ldap 1.3

    step A. createa user in AD like this:

    Attributes personAttributes = new BasicAttributes();

    personAttributes.put( "objectclass", "person" );
    personAttributes.put( "objectclass", "user" );
    personAttributes.put( "givenName", luzer.getFirstName() );
    personAttributes.put( "userPrincipalName", luzer.getEmailAddress() );
    personAttributes.put( "sn", luzer.getLastName());
    personAttributes.put( "description", "Created via WFM 5.0 Flex app" );
    personAttributes.put( "sAMAccountName", luzer.getFirstName().toUpperCase()+ "." + luzer.getLastName().toUpperCase() );
    personAttributes.put( "userAccountControl", "512" ); /// 512 = normal luser
    personAttributes.put( "pwdLastSet", "0" ); /// force user to change password on next login......


    // PASSWORD stuff.....
    personAttributes.put("unicodepwd", encodePassword( luzer.getPassword() ) );

    // Set up user distinguished name and clreate it.
    DistinguishedName newUserDN = userToDistinguishedName( luzer );
    ldapTemplate.bind(newUserDN, null, personAttributes);


    All goes well....
    User tries to authenticate first time we get back ".... AcceptSecurityContext error, data 773 ....." which means:
    // 52e - invalid credentials
    // 530 - not permitted to logon at this time
    // 532 - password expired
    // 533 - account disabled
    // 701 - account expired
    // 773 - user must reset password

    So user is forced to change password. and we do i like this:

    ModificationItem repitem = new ModificationItem( DirContext.REPLACE_ATTRIBUTE, new BasicAttribute("unicodepwd", encodePassword( luzer.getPassword() )) );
    DistinguishedName userDN = userToDistinguishedName( luzer );
    ldapTemplate.modifyAttributes( userDN, new ModificationItem[] { repitem } );

    all goes well.....
    but now user can not log in anymore......

    org.springframework.security.AuthenticationService Exception: [LDAP: error code 32 - 0000208D: NameErr: DSID-031001BD, problem 2001 (NO_OBJECT), data 0, best match of:
    'OU=TRX DEV,OU=WFM LDAP,OU=External Clients,DC=trxfs,DC=trx,DC=com'

    so what the heck is going on?
    ldap base is pointing to
    OU=TRX DEV,OU=WFM LDAP,OU=External Clients,DC=trxfs,DC=trx,DC=com

    so we create and modify users right at the "root"....
    I have spent all day on this and all permutations produce same results.
    reseting password with remove+add attribute produces same results....

  2. #2
    Join Date
    Mar 2005
    Location
    Landskrona, Sweden
    Posts
    505

    Default

    Could you please provide your configuration, the userToDistinguishedName code, and the code you're using for authentication? That would greatly simplify tracking down this problem.
    Mattias Arthursson
    Jayway AB (www.jayway.se)
    Spring-LDAP project member

  3. #3
    Join Date
    Feb 2009
    Posts
    7

    Default CODE for modifying managingin AD

    public void createUser(User luzer) throws DuplicateUserException, PasswordStrengthException, LdapSaveException {
    try {
    Attributes personAttributes = new BasicAttributes();

    personAttributes.put( "objectclass", "person" );
    personAttributes.put( "objectclass", "user" );
    personAttributes.put( "givenName", luzer.getFirstName() );
    personAttributes.put( "userPrincipalName", luzer.getEmailAddress() );
    personAttributes.put( "sn", luzer.getLastName());
    personAttributes.put( "description", "Created via WFM 5.0 Flex app" );
    personAttributes.put( "sAMAccountName", luzer.getFirstName().toUpperCase()+ "." + luzer.getLastName().toUpperCase() );
    personAttributes.put( "userAccountControl", "512" ); /// 512 = normal luser
    personAttributes.put( "pwdLastSet", "0" ); /// force user to change password on next login......

    // PASSWORD stuff.....
    personAttributes.put("unicodepwd", encodePassword( luzer.getPassword() ) );

    // Set up user distinguished name and clreate it.
    DistinguishedName newUserDN = userToDistinguishedName( luzer );
    ldapTemplate.bind(newUserDN, null, personAttributes);

    } catch ( InvalidAttributeValueException exc ) {
    logger.error( "createUser()", exc);
    throw new LdapSaveException( exc.getMessage() );
    } catch ( NameAlreadyBoundException exc ) { /// USER EXISTS....
    logger.error( "createUser()", exc);
    throw new DuplicateUserException( "User ["+ luzer.getEmailAddress() + "] allready exists in AD." );
    } catch ( NameNotFoundException exc ) {
    logger.error( "createUser()", exc);
    throw new LdapSaveException( exc.getMessage() );
    } catch ( OperationNotSupportedException exc ) { // CAN NOT ADD USER
    logger.error( "createUser()", exc);
    throw new PasswordStrengthException( exc.getMessage() );
    } catch ( Exception exc ) {
    logger.error( "createUser()", exc);
    throw new LdapSaveException( exc.getMessage() );
    }
    }

    public void changePassword( User luzer ) throws PasswordStrengthException {
    try {
    ModificationItem repitem = new ModificationItem( DirContext.REPLACE_ATTRIBUTE, new BasicAttribute("unicodepwd", encodePassword( luzer.getPassword() )) );
    DistinguishedName userDN = userToDistinguishedName( luzer );
    ldapTemplate.modifyAttributes( userDN, new ModificationItem[] { repitem } );
    } catch ( Exception exc ) {
    logger.error( "changePassword()", exc);
    throw new PasswordStrengthException( exc.getMessage() );
    }
    }


    private byte[] encodePassword(String password) throws UnsupportedEncodingException {
    String newQuotedPassword = "\"" + password + "\"";
    return newQuotedPassword.getBytes("UTF-16LE");
    }

    private DistinguishedName userToDistinguishedName( User luzer ) {
    return new DistinguishedName( "cn=user_"+luzer.getUserId() ); // cn=user_12345
    }

  4. #4
    Join Date
    Feb 2009
    Posts
    7

    Default Authentication code

    public class ADBindAuthenticator extends AbstractLdapAuthenticator {

    protected static final Logger logger = Logger.getLogger( ADBindAuthenticator.class );

    public ADBindAuthenticator(SpringSecurityContextSource contextSource) {
    super(contextSource);
    }

    public DirContextOperations authenticate(Authentication authentication) {
    DirContextOperations user = null;
    Assert.isInstanceOf(UsernamePasswordAuthentication Token.class, authentication, "Can only process UsernamePasswordAuthenticationToken objects");

    String username = authentication.getName();
    String password = (String)authentication.getCredentials();

    // If DN patterns are configured, try authenticating with them directly
    Iterator<?> dns = getUserDns(username).iterator();

    while (dns.hasNext() && user == null) {
    user = bindWithDn((String) dns.next(), username, password);
    }

    // Otherwise use the configured locator to find the user
    // and authenticate with the returned DN.
    if (user == null && getUserSearch() != null) {
    DirContextOperations userFromSearch = getUserSearch().searchForUser(username);
    user = bindWithDn(userFromSearch.getDn().toString(), username, password);
    }

    if (user == null) {
    throw new BadCredentialsException(messages.getMessage("BindA uthenticator.badCredentials", "Bad credentials"));
    }

    return user;
    }

    private DirContextOperations bindWithDn(String userDn, String username, String password) {

    SpringSecurityLdapTemplate template = new SpringSecurityLdapTemplate( new BindWithSpecificDnContextSource((SpringSecurityCon textSource) getContextSource(), userDn, password));

    try {
    return template.retrieveEntry(userDn, getUserAttributes());

    } catch (BadCredentialsException e) {
    // 52e - invalid credentials
    // 530 - not permitted to logon at this time
    // 532 - password expired
    // 533 - account disabled
    // 701 - account expired
    // 773 - user must reset password
    if( e.getMessage().indexOf( "AcceptSecurityContext error, data 773" ) >= 0 )
    throw new BadCredentialsException("MUST_CHANGE_PASSWORD");

    if( e.getMessage().indexOf( "AcceptSecurityContext error, data 532" ) >= 0 )
    throw new BadCredentialsException("PASSWORD_EXPIRED");

    if( e.getMessage().indexOf( "AcceptSecurityContext error, data 533" ) >= 0 )
    throw new BadCredentialsException("ACCOUNT_DISABLED");

    if( e.getMessage().indexOf( "AcceptSecurityContext error, data 701" ) >= 0 )
    throw new BadCredentialsException("ACCOUNT_EXPIRED");

    if( e.getMessage().indexOf( "AcceptSecurityContext error, data 530" ) >= 0 )
    throw new BadCredentialsException("NOT_ALLOWED_LOGON");

    if( e.getMessage().indexOf( "AcceptSecurityContext error, data 52e" ) >= 0 )
    throw new BadCredentialsException("INVALID_CREDENTIALS");

    }
    return null;
    }

    private class BindWithSpecificDnContextSource implements ContextSource {
    private SpringSecurityContextSource ctxFactory;
    DistinguishedName userDn;
    private String password;

    public BindWithSpecificDnContextSource(SpringSecurityCont extSource ctxFactory, String userDn, String password) {
    this.ctxFactory = ctxFactory;
    this.userDn = new DistinguishedName(userDn);
    this.userDn.prepend(ctxFactory.getBaseLdapPath());
    this.password = password;
    }

    public DirContext getReadOnlyContext() throws DataAccessException {
    return ctxFactory.getReadWriteContext(userDn.toString(), password);
    }

    public DirContext getReadWriteContext() throws DataAccessException {
    return getReadOnlyContext();
    }

    public DirContext getContext(String principal, String credentials) throws NamingException {
    return getReadOnlyContext();
    }
    }

    }

  5. #5
    Join Date
    Feb 2009
    Posts
    7

    Default Config

    <bean id="password-reset-service" class="com.trx.wfm.svc.PasswordResetService" parent="base-service">
    <property name="ldapUserDAO" ref="ldapUserDAO" />
    <property name="ldapProvider" ref="ldapProvider" />
    <property name="userDao" ref="user-dao"/>
    </bean>

    <bean id="ldapUserSearch" class="org.springframework.security.ldap.search.Fi lterBasedLdapUserSearch">
    <constructor-arg index="0" value="${ldap.user.base}" />
    <constructor-arg index="1" value="(&amp;(userPrincipalName={0}))" />
    <constructor-arg index="2" ref="initialDirContextFactory" />
    </bean>

    <bean id="authenticator" class="com.trx.wfm.security.ADBindAuthenticator">
    <constructor-arg ref="initialDirContextFactory" />
    <property name="userSearch" ref="ldapUserSearch" />
    </bean>

    <bean id="populator" class="org.springframework.security.ldap.populator .DefaultLdapAuthoritiesPopulator">
    <constructor-arg ref="initialDirContextFactory" />
    <constructor-arg value="ou=Corp" />
    <property name="groupRoleAttribute" value="ou" />
    </bean>

    <bean id="initialDirContextFactory" class="org.springframework.security.ldap.DefaultSp ringSecurityContextSource">
    <constructor-arg value="${ldap.url}" />
    <property name="base" value="${ldap.base}" />
    <property name="userDn" value="${ldap.admin.bind.userdn}" />
    <property name="password" value="${ldap.admin.bind.password}" />
    </bean>

    <bean id="ldapProvider" class="org.springframework.security.providers.ldap .LdapAuthenticationProvider">
    <constructor-arg ref="authenticator" />
    <constructor-arg ref="populator" />
    </bean>

    <bean id="ldapAuthenticationProvider" class="com.trx.wfm.security.LdapWfmAuthenticationP rovider">
    <property name="ldapProvider" ref="ldapProvider" />
    <property name="userdao" ref="user-dao" />
    </bean>

    <bean id="ldapContextSource" class="org.springframework.ldap.core.support.LdapC ontextSource">
    <property name="url" value="${ldap.url}" />
    <property name="base" value="${ldap.base}" />
    <property name="userDn" value="${ldap.admin.bind.userdn}" />
    <property name="password" value="${ldap.admin.bind.password}" />
    </bean>

    <bean id="ldapTemplate" class="org.springframework.ldap.core.LdapTemplate" >
    <property name="contextSource" ref="ldapContextSource" />
    </bean>

    <bean id="ldapUserDAO" class="com.trx.wfm.model.dao.LdapUserDAO">
    <property name="ldapTemplate" ref="ldapTemplate" />
    <property name="ldapReadonly" value="${ldap.readonly}" />
    <property name="ldapBase" value="${ldap.base}" />
    </bean>

    ldap.url=ldaps://host:636
    ldap.user.base=
    ldap.base=OU=TRX DEV,OU=WFM LDAP,OU=External Clients,DC=trxfs,DC=trx,DC=com
    ldap.admin.bind.userdn=CN=xxxxxx,OU=WFM LDAP,OU=External Clients,DC=trxfs,DC=trx,DC=com

  6. #6
    Join Date
    Feb 2009
    Posts
    7

    Default UNIT test

    public void test_1_CreateAndChangePassword() {

    LdapUserDAO ldap = (LdapUserDAO)applicationContext.getBean("ldapUserD AO");

    User user = new User();
    user.setUserId(1001);
    user.setEmailAddress("AAAAA@bbb.con");
    user.setFirstName( "Testing" );
    user.setLastName( "Account" );
    user.setPassword( "c0mpl3xp@s" );

    try {

    ldap.createUser(user);

    user.setPassword( "c1mp24xp#s" );

    ldap.changePassword(user);

    LdapAuthenticationProvider ldapProvider = (LdapAuthenticationProvider)applicationContext.get Bean("ldapProvider");
    Authentication auth = new UsernamePasswordAuthenticationToken(user.getEmailA ddress(), user.getPassword());
    auth = ldapProvider.authenticate(auth);

    } catch ( Exception exc ) {
    exc.printStackTrace();
    fail( exc.getMessage() );
    }
    }

  7. #7
    Join Date
    Feb 2009
    Posts
    7

    Default

    public Principal doAuthentication(String username, Object credentials) {
    Authentication auth = new UsernamePasswordAuthenticationToken(username, credentials);
    String password = (String) credentials;
    if (password == null || password.length() < 8) {
    SecurityException sex = new SecurityException();
    sex.setMessage("invalid password");
    throw sex;
    }

    try {
    // org.springframework.security.providers.ldap.LdapAu thenticationProvider
    auth = ldapProvider.authenticate(auth);
    // } catch (AuthenticationException ex) {
    } catch (Exception ex) {
    ex.printStackTrace();
    SecurityException sex = new SecurityException();
    sex.setMessage( ex.getMessage() );
    sex.initCause(ex);
    sex.setDetails(ex.getMessage());
    sex.setCode(SecurityException.CLIENT_AUTHENTICATIO N_CODE);
    throw sex;
    }

    try {
    User user = userdao.findByEmail(username);
    FlexSession session = FlexContext.getFlexSession();
    session.setAttribute(WfmConstants.WFM_USER , user);
    } catch (Exception ex) {
    SecurityException sex = new SecurityException();
    sex.initCause(ex);
    sex.setMessage("user in ldap, but not WFM database");
    throw sex;
    }

    return new UserPrincipal(auth.getName());

    }

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •