keycloak-aplcache

KEYCLOAK-2634 Better error reporting if password update failed

3/14/2016 9:35:30 AM

Details

diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/store/ldap/LDAPIdentityStore.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/store/ldap/LDAPIdentityStore.java
index b8adbdd..9a9b929 100644
--- a/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/store/ldap/LDAPIdentityStore.java
+++ b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/store/ldap/LDAPIdentityStore.java
@@ -220,6 +220,8 @@ public class LDAPIdentityStore implements IdentityStore {
                 mods[0] = new ModificationItem(DirContext.REPLACE_ATTRIBUTE, mod0);
 
                 operationManager.modifyAttribute(userDN, mod0);
+            } catch (ModelException me) {
+                throw me;
             } catch (Exception e) {
                 throw new ModelException("Error updating password.", e);
             }
@@ -240,6 +242,8 @@ public class LDAPIdentityStore implements IdentityStore {
             modItems.add(new ModificationItem(DirContext.REPLACE_ATTRIBUTE, unicodePwd));
 
             operationManager.modifyAttributes(userDN, modItems.toArray(new ModificationItem[] {}));
+        } catch (ModelException me) {
+            throw me;
         } catch (Exception e) {
             throw new ModelException(e);
         }
diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/mappers/msad/MSADUserAccountControlMapper.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/mappers/msad/MSADUserAccountControlMapper.java
index 88f12fb..033b3f4 100644
--- a/federation/ldap/src/main/java/org/keycloak/federation/ldap/mappers/msad/MSADUserAccountControlMapper.java
+++ b/federation/ldap/src/main/java/org/keycloak/federation/ldap/mappers/msad/MSADUserAccountControlMapper.java
@@ -30,6 +30,7 @@ import org.keycloak.federation.ldap.idm.model.LDAPObject;
 import org.keycloak.federation.ldap.idm.query.internal.LDAPQuery;
 import org.keycloak.federation.ldap.mappers.AbstractLDAPFederationMapper;
 import org.keycloak.models.LDAPConstants;
+import org.keycloak.models.ModelException;
 import org.keycloak.models.RealmModel;
 import org.keycloak.models.UserCredentialModel;
 import org.keycloak.models.UserFederationMapperModel;
@@ -48,6 +49,7 @@ public class MSADUserAccountControlMapper extends AbstractLDAPFederationMapper {
     private static final Logger logger = Logger.getLogger(MSADUserAccountControlMapper.class);
 
     private static final Pattern AUTH_EXCEPTION_REGEX = Pattern.compile(".*AcceptSecurityContext error, data ([0-9a-f]*), v.*");
+    private static final Pattern AUTH_INVALID_NEW_PASSWORD = Pattern.compile(".*error code ([0-9a-f]+) .*WILL_NOT_PERFORM.*");
 
     public MSADUserAccountControlMapper(UserFederationMapperModel mapperModel, LDAPFederationProvider ldapProvider, RealmModel realm) {
         super(mapperModel, ldapProvider, realm);
@@ -94,7 +96,7 @@ public class MSADUserAccountControlMapper extends AbstractLDAPFederationMapper {
     }
 
     protected boolean processAuthErrorCode(String errorCode, UserModel user) {
-        logger.debugf("MSAD Error code is '%s' after failed LDAP login of user", errorCode, user.getUsername());
+        logger.debugf("MSAD Error code is '%s' after failed LDAP login of user '%s'", errorCode, user.getUsername());
 
         if (ldapProvider.getEditMode() == UserFederationProvider.EditMode.WRITABLE) {
             if (errorCode.equals("532") || errorCode.equals("773")) {
@@ -105,6 +107,8 @@ public class MSADUserAccountControlMapper extends AbstractLDAPFederationMapper {
                 // User is disabled in MSAD. Set him to disabled in KC as well
                 user.setEnabled(false);
                 return true;
+            } else if (errorCode.equals("775")) {
+                logger.warnf("Locked user '%s' attempt to login", user.getUsername());
             }
         }
 
@@ -112,6 +116,22 @@ public class MSADUserAccountControlMapper extends AbstractLDAPFederationMapper {
     }
 
 
+    protected ModelException processFailedPasswordUpdateException(ModelException e) {
+        String exceptionMessage = e.getCause().getMessage().replace('\n', ' ');
+        Matcher m = AUTH_INVALID_NEW_PASSWORD.matcher(exceptionMessage);
+        if (m.matches()) {
+            String errorCode = m.group(1);
+            if (errorCode.equals("53")) {
+                ModelException me = new ModelException("invalidPasswordRegexPatternMessage", e);
+                me.setParameters(new Object[]{"passwordConstraintViolation"});
+                return me;
+            }
+        }
+
+        return e;
+    }
+
+
     public class MSADUserModelDelegate extends UserModelDelegate {
 
         private final LDAPObject ldapUser;
@@ -156,7 +176,12 @@ public class MSADUserAccountControlMapper extends AbstractLDAPFederationMapper {
         @Override
         public void updateCredential(UserCredentialModel cred) {
             // Update LDAP password first
-            super.updateCredential(cred);
+            try {
+                super.updateCredential(cred);
+            } catch (ModelException me) {
+                me = processFailedPasswordUpdateException(me);
+                throw me;
+            }
 
             if (ldapProvider.getEditMode() == UserFederationProvider.EditMode.WRITABLE && cred.getType().equals(UserCredentialModel.PASSWORD)) {
                 logger.debugf("Going to update userAccountControl for ldap user '%s' after successful password update", ldapUser.getDn().toString());