diff --git a/src/main/java/org/olat/admin/user/bulkChange/UserBulkChangePasswordController.java b/src/main/java/org/olat/admin/user/bulkChange/UserBulkChangePasswordController.java
index 1f100cc31ee20c0500e09c56d3c4de5d9cdb8d96..73b8e69758d14142618816bcf9ef9779a47ca7f7 100644
--- a/src/main/java/org/olat/admin/user/bulkChange/UserBulkChangePasswordController.java
+++ b/src/main/java/org/olat/admin/user/bulkChange/UserBulkChangePasswordController.java
@@ -24,8 +24,9 @@
 */
 package org.olat.admin.user.bulkChange;
 
+import org.apache.logging.log4j.Logger;
 import org.olat.basesecurity.BaseSecurity;
-import org.olat.core.CoreSpringFactory;
+import org.olat.basesecurity.BaseSecurityModule;
 import org.olat.core.gui.UserRequest;
 import org.olat.core.gui.components.Component;
 import org.olat.core.gui.components.form.flexible.FormItemContainer;
@@ -41,7 +42,6 @@ import org.olat.core.gui.control.Event;
 import org.olat.core.gui.control.WindowControl;
 import org.olat.core.gui.control.controller.BasicController;
 import org.olat.core.id.Identity;
-import org.apache.logging.log4j.Logger;
 import org.olat.core.logging.Tracing;
 import org.olat.login.auth.OLATAuthManager;
 import org.olat.registration.RegistrationManager;
@@ -63,18 +63,19 @@ public class UserBulkChangePasswordController extends BasicController {
 	private static final Logger log = Tracing.createLoggerFor(UserBulkChangePasswordController.class);
 	
 	private ChangePasswordForm changePasswordForm;
-	private final OLATAuthManager olatAuthenticationSpi;
 	
 	@Autowired
 	private BaseSecurity securityManager;
 	@Autowired
+	private BaseSecurityModule securityModule;
+	@Autowired
+	private OLATAuthManager olatAuthenticationSpi;
+	@Autowired
 	private RegistrationManager registrationManager;
 
 	public UserBulkChangePasswordController(UserRequest ureq, WindowControl wControl) {
 		super(ureq, wControl);
 		
-		olatAuthenticationSpi = CoreSpringFactory.getImpl(OLATAuthManager.class);
-
 		Panel main = new Panel("changePsw");
 		VelocityContainer mainVC = createVelocityContainer("index");
 		
@@ -109,29 +110,35 @@ public class UserBulkChangePasswordController extends BasicController {
 			for(String username:usernames) {
 				if (username.length()==0) continue;
 				try {
-					Identity identity = securityManager.findIdentityByName(username);
+					
+					Identity identity;
+					if(securityModule.isIdentityNameAutoGenerated()) {
+						identity = securityManager.findIdentityByNickName(username);
+					} else {
+						identity = securityManager.findIdentityByName(username);
+					}
 					if(identity!=null) {
 						if (password!=null && password.trim().length()>0) {
 							olatAuthenticationSpi.changePassword(ureq.getIdentity(), identity, password);	
-							log.info("changePassword for username: " + username);
+							log.info("changePassword for username: {} of identity: {}", username, identity);
 						}
 						if (autodisc) {
 							registrationManager.setHasConfirmedDislaimer(identity);
-							log.info("Disclaimer accepted for username: " + username);
+							log.info("Disclaimer accepted for username: {}", username);
 						}
 						if (langGerman) {
 							identity.getUser().getPreferences().setLanguage("de");
 							UserManager.getInstance().updateUserFromIdentity(identity);
-							log.info("Set language German for username: " + username);
+							log.info("Set language German for username: {}", username);
 						}
 						
 						c++;
 						
 					}	else {							 
-						log.warn("could find user with username: " + username);
+						log.warn("could find user with username: {}", username);
 					}
 				} catch (Exception e) {
-					log.error("Failed to change password/settings for username: " + username, e);
+					log.error("Failed to change password/settings for username: {}", username, e);
 				}
 			}				
 			
diff --git a/src/main/java/org/olat/admin/user/imp/TransientIdentity.java b/src/main/java/org/olat/admin/user/imp/TransientIdentity.java
index fc82ef41087376953a47fbe6f4d591ca9eef4714..eaa0276b2a0c61f4f5199b30b3c6d34561778e6d 100644
--- a/src/main/java/org/olat/admin/user/imp/TransientIdentity.java
+++ b/src/main/java/org/olat/admin/user/imp/TransientIdentity.java
@@ -79,6 +79,11 @@ public class TransientIdentity implements Identity, User {
 	public String getLastName() {
 		return properties.get(UserConstants.LASTNAME);
 	}
+	
+	@Override
+	public String getNickName() {
+		return properties.get(UserConstants.NICKNAME);
+	}
 
 	@Override
 	public String getEmail() {
diff --git a/src/main/java/org/olat/admin/user/imp/UpdateIdentity.java b/src/main/java/org/olat/admin/user/imp/UpdateIdentity.java
index 2fb6fc856d32f111de59c0d529b5fa0b9c27d5be..4667a5496ceb6d74d6f6e08f44e66c0d5888f540 100644
--- a/src/main/java/org/olat/admin/user/imp/UpdateIdentity.java
+++ b/src/main/java/org/olat/admin/user/imp/UpdateIdentity.java
@@ -168,6 +168,11 @@ public class UpdateIdentity implements Identity {
 			return updatedProperties.get(UserConstants.LASTNAME);
 		}
 
+		@Override
+		public String getNickName() {
+			return updatedProperties.get(UserConstants.NICKNAME);
+		}
+
 		@Override
 		public String getEmail() {
 			return updatedProperties.get(UserConstants.EMAIL);
diff --git a/src/main/java/org/olat/admin/user/imp/UserImportController.java b/src/main/java/org/olat/admin/user/imp/UserImportController.java
index 303b88bdcb3ae729e2da9da43e842c08d65adf2b..c8188dceb86b1f3bc922733d172f5576ec2a64c6 100644
--- a/src/main/java/org/olat/admin/user/imp/UserImportController.java
+++ b/src/main/java/org/olat/admin/user/imp/UserImportController.java
@@ -208,8 +208,9 @@ public class UserImportController extends BasicController {
 			report.incrementCreatedUser();
 			report.incrementUpdatedLdapAuthentication();
 		} else {
+			String provider = StringHelper.containsNonWhitespace(pwd) ? BaseSecurityModule.getDefaultAuthProviderIdentifier() : null;
 			ident = securityManager.createAndPersistIdentityAndUserWithOrganisation(identityName, login, null, newUser,
-					BaseSecurityModule.getDefaultAuthProviderIdentifier(), login, pwd,  preselectedOrganisation);
+					provider, login, pwd,  preselectedOrganisation);
 			report.incrementCreatedUser();
 		}
 		return ident;
diff --git a/src/main/java/org/olat/basesecurity/BaseSecurity.java b/src/main/java/org/olat/basesecurity/BaseSecurity.java
index 62d200bfa07a285eece236a9c6c446a04e6a98f7..d2a4e4d04a2c8b524f46924e9eca1c512ef4c20d 100644
--- a/src/main/java/org/olat/basesecurity/BaseSecurity.java
+++ b/src/main/java/org/olat/basesecurity/BaseSecurity.java
@@ -87,6 +87,8 @@ public interface BaseSecurity {
 	public boolean isGuest(IdentityRef identity);
 	
 	public Identity findIdentityByLogin(String login);
+	
+	public Identity findIdentityByNickName(String name);
 
 	/**
 	 * Find an identity by its name. This is an exact match. Use the
diff --git a/src/main/java/org/olat/basesecurity/BaseSecurityManager.java b/src/main/java/org/olat/basesecurity/BaseSecurityManager.java
index 41566256ffd9d6e49936fa28203bf250e06128c6..fe94aa2c0eb09054617c4d3527c2d99568579876 100644
--- a/src/main/java/org/olat/basesecurity/BaseSecurityManager.java
+++ b/src/main/java/org/olat/basesecurity/BaseSecurityManager.java
@@ -428,8 +428,18 @@ public class BaseSecurityManager implements BaseSecurity, UserDataDeletable {
 	@Override
 	public Identity findIdentityByName(String identityName) {
 		return identityDao.findIdentityByName(identityName);
-	}
+	}	
 	
+	@Override
+	public Identity findIdentityByNickName(String name) {
+		List<Identity> identities = identityDao.findIdentitiesByNickName(name);
+		if(identities != null && identities.size() > 1) {
+			log.warn("Nick name is not unique: {}", name);
+			return null;
+		}
+		return identities != null && identities.size() == 1 ? identities.get(0) : null;
+	}
+
 	@Override
 	public Identity findIdentityByNameCaseInsensitive(String identityName) {
 		if (identityName == null) throw new AssertException("findIdentitybyName: name was null");
diff --git a/src/main/java/org/olat/basesecurity/manager/IdentityDAO.java b/src/main/java/org/olat/basesecurity/manager/IdentityDAO.java
index 35720d6fec68bb7c922948f3edffb7e727982228..e82cc6a1741ed43f5de0abc143ba3fe94ec715e5 100644
--- a/src/main/java/org/olat/basesecurity/manager/IdentityDAO.java
+++ b/src/main/java/org/olat/basesecurity/manager/IdentityDAO.java
@@ -74,6 +74,20 @@ public class IdentityDAO {
 		return identities.get(0);
 	}
 	
+	public List<Identity> findIdentitiesByNickName(String name) {
+		if(!StringHelper.containsNonWhitespace(name)) return new ArrayList<>();
+
+		StringBuilder sb = new StringBuilder(128);
+		sb.append("select ident from ").append(IdentityImpl.class.getName()).append(" as ident")
+		  .append(" inner join fetch ident.user user")
+		  .append(" where user.nickName=:username");
+		
+		return dbInstance.getCurrentEntityManager()
+				.createQuery(sb.toString(), Identity.class)
+				.setParameter("username", name)
+				.getResultList();
+	}
+	
 	public List<FindNamedIdentity> findByNames(Collection<String> names) {
 		StringBuilder sb = new StringBuilder();
 		sb.append("select ident, auth from ").append(IdentityImpl.class.getName()).append(" as ident")
diff --git a/src/main/java/org/olat/basesecurity/model/QueryUserHelper.java b/src/main/java/org/olat/basesecurity/model/QueryUserHelper.java
index 6bce3b909d7f277de20893600aa853ea00958d0d..3f6375b65d7463664619d4d6837ea243c49f5041 100644
--- a/src/main/java/org/olat/basesecurity/model/QueryUserHelper.java
+++ b/src/main/java/org/olat/basesecurity/model/QueryUserHelper.java
@@ -65,6 +65,11 @@ public class QueryUserHelper implements User {
 		return null;
 	}
 
+	@Override
+	public String getNickName() {
+		return null;
+	}
+
 	@Override
 	public String getEmail() {
 		return null;
diff --git a/src/main/java/org/olat/core/id/User.java b/src/main/java/org/olat/core/id/User.java
index 74c476e402b410d08ee023d7c10b8f0175bd42e7..416b5efe1d74de4f5ea02536e22ca75a5b935f68 100644
--- a/src/main/java/org/olat/core/id/User.java
+++ b/src/main/java/org/olat/core/id/User.java
@@ -48,6 +48,8 @@ public interface User extends CreateInfo, Persistable {
 	
 	public String getLastName();
 	
+	public String getNickName();
+	
 	public String getEmail();
 	
 	public String getInstitutionalEmail();
diff --git a/src/main/java/org/olat/core/util/mail/ui/EMailIdentity.java b/src/main/java/org/olat/core/util/mail/ui/EMailIdentity.java
index 9814ff94cde5cbab6673885831ed3a7a28c43d74..69af87462bcedb96ecbc107ac2957d1ca4beb16c 100644
--- a/src/main/java/org/olat/core/util/mail/ui/EMailIdentity.java
+++ b/src/main/java/org/olat/core/util/mail/ui/EMailIdentity.java
@@ -121,6 +121,11 @@ public class EMailIdentity implements Identity {
 			return data.get(UserConstants.LASTNAME);
 		}
 		
+		@Override
+		public String getNickName() {
+			return data.get(UserConstants.NICKNAME);
+		}
+
 		@Override
 		public String getEmail() {
 			return data.get(UserConstants.EMAIL);
diff --git a/src/main/java/org/olat/course/run/preview/PreviewIdentity.java b/src/main/java/org/olat/course/run/preview/PreviewIdentity.java
index 45c419ebebb4e061af2b84690173037c545477b1..7eaa1570696c97060ae9beccf7f97f9526f08103 100644
--- a/src/main/java/org/olat/course/run/preview/PreviewIdentity.java
+++ b/src/main/java/org/olat/course/run/preview/PreviewIdentity.java
@@ -74,6 +74,11 @@ public final class PreviewIdentity implements Identity, User {
 		return "JaneDoe";
 	}
 	
+	@Override
+	public String getNickName() {
+		return "u" + getKey();
+	}
+
 	@Override
 	public String getEmail() {
 		return data.get(UserConstants.EMAIL);
diff --git a/src/main/java/org/olat/ldap/LDAPLoginManager.java b/src/main/java/org/olat/ldap/LDAPLoginManager.java
index a937094eb06c88f854d11195074ed513deb943cb..3d0a79b879acd133dab88d90f0d9d195cc2fc995 100644
--- a/src/main/java/org/olat/ldap/LDAPLoginManager.java
+++ b/src/main/java/org/olat/ldap/LDAPLoginManager.java
@@ -27,6 +27,7 @@ import java.util.Map;
 import javax.naming.directory.Attributes;
 import javax.naming.ldap.LdapContext;
 
+import org.olat.basesecurity.Authentication;
 import org.olat.basesecurity.IdentityRef;
 import org.olat.core.id.Identity;
 import org.olat.core.id.OLATResourceable;
@@ -42,7 +43,7 @@ public interface LDAPLoginManager {
 	
 	public Identity authenticate(String username, String pwd, LDAPError ldapError);
 
-	public boolean changePassword(Identity identity, String pwd, LDAPError errors);
+	public boolean changePassword(Authentication auth, String pwd, LDAPError errors);
 	
 
 	public Identity createAndPersistUser(String uid);
diff --git a/src/main/java/org/olat/ldap/manager/LDAPLoginManagerImpl.java b/src/main/java/org/olat/ldap/manager/LDAPLoginManagerImpl.java
index 03c9851ac7a14e22c8388334baca5ca6dd72f1b5..2856073e7882a677c0fcf1407f116384d0107a63 100644
--- a/src/main/java/org/olat/ldap/manager/LDAPLoginManagerImpl.java
+++ b/src/main/java/org/olat/ldap/manager/LDAPLoginManagerImpl.java
@@ -405,13 +405,11 @@ public class LDAPLoginManagerImpl implements LDAPLoginManager, AuthenticationPro
 	
 	/**
 	 * Change the password on the LDAP server.
-	 * @see org.olat.ldap.LDAPLoginManager#changePassword(org.olat.core.id.Identity, java.lang.String, org.olat.ldap.LDAPError)
 	 */
 	@Override
-	public boolean changePassword(Identity identity, String pwd, LDAPError errors) {
-		String uid = identity.getName();//TODO username
-		
-		
+	public boolean changePassword(Authentication auth, String pwd, LDAPError errors) {
+		String uid = auth.getAuthusername();
+	
 		String ldapUserPasswordAttribute = syncConfiguration.getLdapUserPasswordAttribute();
 		try {
 			LdapContext ctx = bindSystem();
@@ -849,13 +847,16 @@ public class LDAPLoginManagerImpl implements LDAPLoginManager, AuthenticationPro
 				return defaultAuth.getIdentity();
 			}
 			
-			if(!securityModule.isIdentityNameAutoGenerated()) {
-				Identity identity = securityManager.findIdentityByName(uid);
-				if(identity != null) {
-					securityManager.createAndPersistAuthentication(identity, LDAPAuthenticationController.PROVIDER_LDAP, token, null, null);
-					log.info("Found identity by identity name that was not yet in LDAP security group. Converted user::{} to be an LDAP managed user", uid);
-					return identity;
-				}
+			Identity identity = null;
+			if(securityModule.isIdentityNameAutoGenerated()) {
+				identity = securityManager.findIdentityByNickName(uid);
+			} else {
+				identity = securityManager.findIdentityByName(uid);
+			}
+			if(identity != null) {
+				securityManager.createAndPersistAuthentication(identity, LDAPAuthenticationController.PROVIDER_LDAP, token, null, null);
+				log.info(Tracing.M_AUDIT, "Found identity by identity name that was not yet in LDAP security group. Converted user::{} to be an LDAP managed user", uid);
+				return identity;
 			}
 		}
 		return null;
diff --git a/src/main/java/org/olat/login/auth/OLATAuthManager.java b/src/main/java/org/olat/login/auth/OLATAuthManager.java
index 2c956687e8095f08e98074246d8074a58dca1a49..41be246a020b0a6faf801b712e2cd6e96e45459b 100644
--- a/src/main/java/org/olat/login/auth/OLATAuthManager.java
+++ b/src/main/java/org/olat/login/auth/OLATAuthManager.java
@@ -33,6 +33,7 @@ import java.util.Map;
 import org.apache.logging.log4j.Logger;
 import org.olat.basesecurity.Authentication;
 import org.olat.basesecurity.BaseSecurity;
+import org.olat.basesecurity.BaseSecurityModule;
 import org.olat.basesecurity.IdentityRef;
 import org.olat.basesecurity.manager.AuthenticationDAO;
 import org.olat.core.commons.services.webdav.manager.WebDAVAuthManager;
@@ -89,6 +90,8 @@ public class OLATAuthManager implements AuthenticationSPI {
 	@Autowired
 	private BaseSecurity securityManager;
 	@Autowired
+	private BaseSecurityModule securityModule;
+	@Autowired
 	private MailManager mailManager;
 	@Autowired
 	private WebDAVAuthManager webDAVAuthManager;
@@ -291,16 +294,16 @@ public class OLATAuthManager implements AuthenticationSPI {
 		if(ldapAuth != null) {
 			if(ldapLoginModule.isPropagatePasswordChangedOnLdapServer()) {
 				LDAPError ldapError = new LDAPError();
-				ldapLoginManager.changePassword(identity, newPwd, ldapError);
+				ldapLoginManager.changePassword(ldapAuth, newPwd, ldapError);
 				log.info(Tracing.M_AUDIT, "{} change the password on the LDAP server for identity: {}", doer.getKey(), identity.getKey());
 				allOk = ldapError.isEmpty();
 
 				if(allOk && ldapLoginModule.isCacheLDAPPwdAsOLATPwdOnLogin()) {
-					allOk &= changeOlatPassword(doer, identity, identity.getName(), newPwd);
+					allOk &= changeOlatPassword(doer, identity, newPwd);
 				}
 			}
 		} else {
-			allOk = changeOlatPassword(doer, identity, identity.getName(), newPwd);
+			allOk = changeOlatPassword(doer, identity, newPwd);
 		}
 		if(allOk) {
 			sendConfirmationEmail(doer, identity);
@@ -347,12 +350,25 @@ public class OLATAuthManager implements AuthenticationSPI {
 	 * @param newPwd
 	 * @return
 	 */
-	public boolean changeOlatPassword(Identity doer, Identity identity, String username, String newPwd) {
+	public boolean changeOlatPassword(Identity doer, Identity identity, String newPwd) {
+		String username;
 		Authentication auth = securityManager.findAuthentication(identity, "OLAT");
 		if (auth == null) { // create new authentication for provider OLAT
+			if(securityModule.isIdentityNameAutoGenerated()) {
+				username = identity.getUser().getNickName();
+			} else {
+				username = identity.getName();
+			}
+			if(!StringHelper.containsNonWhitespace(username) && loginModule.isAllowLoginUsingEmail()) {
+				username = identity.getUser().getEmail();
+				if(!StringHelper.containsNonWhitespace(username)) {
+					username = identity.getUser().getInstitutionalEmail();
+				}
+			}
 			securityManager.createAndPersistAuthentication(identity, "OLAT", username, newPwd, loginModule.getDefaultHashAlgorithm());
-			log.info(Tracing.M_AUDIT, "{} created new authenticatin for identity: {}", doer.getKey(), identity.getKey());
+			log.info(Tracing.M_AUDIT, "{} created new authentication for identity: {} with authusername: {}", doer.getKey(), identity.getKey(), username);
 		} else {
+			username = auth.getAuthusername();
 			securityManager.updateCredentials(auth, newPwd, loginModule.getDefaultHashAlgorithm());
 			log.info(Tracing.M_AUDIT, "{} set new password for identity: {}", doer.getKey(),  identity.getKey());
 		}
diff --git a/src/main/java/org/olat/modules/coach/manager/CoachingDAO.java b/src/main/java/org/olat/modules/coach/manager/CoachingDAO.java
index d12d4095fb163996dd9bf82b215bcb380f4da035..7472e5411cf40ce891d62986cc5ed90fb62eea2f 100644
--- a/src/main/java/org/olat/modules/coach/manager/CoachingDAO.java
+++ b/src/main/java/org/olat/modules/coach/manager/CoachingDAO.java
@@ -1023,9 +1023,8 @@ public class CoachingDAO {
 		return !rawList.isEmpty();
 	}
 	
-
 	private NativeQueryBuilder appendUsersStatisticsJoins(SearchCoachedIdentityParams params, NativeQueryBuilder sb) {
-		if(params != null && params.getUserProperties() != null && params.getUserProperties().size() > 0) {
+		if(StringHelper.containsNonWhitespace(params.getLogin()) || (params != null && params.getUserProperties() != null && params.getUserProperties().size() > 0)) {
 			sb.append(" inner join o_user user_participant on (user_participant.fk_identity=id_participant.id)");
 		}
 		return sb;
@@ -1041,17 +1040,27 @@ public class CoachingDAO {
 		
 		if(StringHelper.containsNonWhitespace(params.getLogin())) {
 			String login = PersistenceHelper.makeFuzzyQueryString(params.getLogin());
+			sb.append(" and (");
+			
 			if (login.contains("_") && dbInstance.isOracle()) {
 				//oracle needs special ESCAPE sequence to search for escaped strings
-				sb.append(" and lower(id_participant.name) like :login ESCAPE '\\'");
+				sb.append(" lower(id_participant.name) like :login ESCAPE '\\'");
 			} else if (dbInstance.isMySQL()) {
-				sb.append(" and id_participant.name like :login");
+				sb.append(" id_participant.name like :login");
 			} else {
-				sb.append(" and lower(id_participant.name) like :login");
+				sb.append(" lower(id_participant.name) like :login");
 			}
-			
-			//TODO login
-			
+			sb.append(" or ");
+			if (login.contains("_") && dbInstance.isOracle()) {
+				//oracle needs special ESCAPE sequence to search for escaped strings
+				sb.append(" lower(user_participant.u_nickname) like :login ESCAPE '\\'");
+			} else if (dbInstance.isMySQL()) {
+				sb.append(" user_participant.u_nickname like :login");
+			} else {
+				sb.append(" lower(user_participant.u_nickname) like :login");
+			}
+			sb.append(")");
+
 			queryParams.put("login", login);
 		}
 		
diff --git a/src/main/java/org/olat/modules/coach/ui/UserSearchForm.java b/src/main/java/org/olat/modules/coach/ui/UserSearchForm.java
index 9dd499f215eb689287ab1bbef927d05c65a54f76..4975844d6ba249e158961001debf4795eb68b284 100644
--- a/src/main/java/org/olat/modules/coach/ui/UserSearchForm.java
+++ b/src/main/java/org/olat/modules/coach/ui/UserSearchForm.java
@@ -22,6 +22,7 @@ package org.olat.modules.coach.ui;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.stream.Collectors;
 
 import org.olat.basesecurity.BaseSecurityModule;
 import org.olat.core.gui.UserRequest;
@@ -36,6 +37,7 @@ import org.olat.core.gui.components.form.flexible.impl.FormLayoutContainer;
 import org.olat.core.gui.control.Controller;
 import org.olat.core.gui.control.Event;
 import org.olat.core.gui.control.WindowControl;
+import org.olat.core.id.UserConstants;
 import org.olat.core.util.StringHelper;
 import org.olat.user.UserManager;
 import org.olat.user.propertyhandlers.EmailProperty;
@@ -86,7 +88,14 @@ public class UserSearchForm extends FormBasicController {
 		login = uifactory.addTextElement("login", "search.form.login", 128, "", formLayout);
 		login.setVisible(adminProps);
 		
-		userPropertyHandlers = userManager.getUserPropertyHandlersFor(PROPS_IDENTIFIER, adminProps);
+		List<UserPropertyHandler> allPropertyHandlers = userManager.getUserPropertyHandlersFor(PROPS_IDENTIFIER, adminProps);
+		if(adminProps) {
+			userPropertyHandlers = allPropertyHandlers.stream()
+					.filter(prop -> !UserConstants.NICKNAME.equals(prop.getName()))
+					.collect(Collectors.toList());
+		} else {
+			userPropertyHandlers = allPropertyHandlers;
+		}
 
 		for (UserPropertyHandler userPropertyHandler : userPropertyHandlers) {
 			if (userPropertyHandler != null) {
diff --git a/src/main/java/org/olat/registration/PwChangeController.java b/src/main/java/org/olat/registration/PwChangeController.java
index a924eca3676b7e3446b5d1e79450d3b9157d548b..6203b6673847855907c1af911e86eeaa01e1d62e 100644
--- a/src/main/java/org/olat/registration/PwChangeController.java
+++ b/src/main/java/org/olat/registration/PwChangeController.java
@@ -27,7 +27,6 @@ package org.olat.registration;
 
 import java.text.DateFormat;
 import java.util.Date;
-import java.util.List;
 import java.util.Locale;
 
 import org.olat.basesecurity.BaseSecurity;
@@ -325,10 +324,7 @@ public class PwChangeController extends BasicController {
 			identity = userManager.findUniqueIdentityByEmail(emailOrUsername);
 		}
 		if (identity == null) {
-			List<Identity> identities = userManager.findIdentitiesWithProperty(UserConstants.NICKNAME, emailOrUsername);
-			if(identities != null && identities.size() == 1) {
-				identity = identities.get(0);
-			}
+			identity = securityManager.findIdentityByNickName(emailOrUsername);
 		}
 		return identity;
 	}
diff --git a/src/main/java/org/olat/upgrade/_spring/databaseUpgradeContext.xml b/src/main/java/org/olat/upgrade/_spring/databaseUpgradeContext.xml
index 350f0d1a7863a0aa27ed1b38a8360214cfe07263..0eaf7eae050ae1b78526584a162b1acb26727c22 100644
--- a/src/main/java/org/olat/upgrade/_spring/databaseUpgradeContext.xml
+++ b/src/main/java/org/olat/upgrade/_spring/databaseUpgradeContext.xml
@@ -280,6 +280,10 @@
 					<constructor-arg index="0" value="OLAT_15.2.0" />
 					<property name="alterDbStatements" value="alter_15_1_x_to_15_2_0.sql" />
 				</bean>
+				<bean id="database_upgrade_15_2_1" class="org.olat.upgrade.DatabaseUpgrade">
+					<constructor-arg index="0" value="OLAT_15.2.1" />
+					<property name="alterDbStatements" value="alter_15_2_x_to_15_2_1.sql" />
+				</bean>
 			</list>
 		</property>
 	</bean>
diff --git a/src/main/java/org/olat/user/UserImpl.java b/src/main/java/org/olat/user/UserImpl.java
index 8d5f39d8337e049c77172c0ae230546db55d85d8..6c4af7bcad2f7a05cd64b370a12c67225a073833 100644
--- a/src/main/java/org/olat/user/UserImpl.java
+++ b/src/main/java/org/olat/user/UserImpl.java
@@ -327,6 +327,7 @@ public class UserImpl implements User {
 		this.lastName = lastName;
 	}
 
+	@Override
 	public String getNickName() {
 		return nickName;
 	}
diff --git a/src/main/java/org/olat/user/propertyhandlers/_spring/userPropertriesHandlersContext.xml b/src/main/java/org/olat/user/propertyhandlers/_spring/userPropertriesHandlersContext.xml
index bc9df16997e7a358e568b455d7a7c6ca0daddb4a..fa6a68fe44c584e406cbf5cd8197cc20c3c1b8d8 100644
--- a/src/main/java/org/olat/user/propertyhandlers/_spring/userPropertriesHandlersContext.xml
+++ b/src/main/java/org/olat/user/propertyhandlers/_spring/userPropertriesHandlersContext.xml
@@ -9,7 +9,7 @@
 	<!-- 
 		Define all available user properties and its handlers 
 	-->
-	<bean id="userPropertyUserNickName" class="org.olat.user.propertyhandlers.Generic127CharTextPropertyHandler">
+	<bean id="userPropertyUserNickName" class="org.olat.user.propertyhandlers.GenericUnique127CharTextPropertyHandler">
 		<property name="name" value="nickName" />
 		<property name="group" value="account" />
 	</bean>
diff --git a/src/main/resources/database/mysql/alter_15_2_x_to_15_2_1.sql b/src/main/resources/database/mysql/alter_15_2_x_to_15_2_1.sql
new file mode 100644
index 0000000000000000000000000000000000000000..d721bdb78d00a31d2c0e3662466ae91a6b996c61
--- /dev/null
+++ b/src/main/resources/database/mysql/alter_15_2_x_to_15_2_1.sql
@@ -0,0 +1,3 @@
+alter table o_user add constraint iuni_user_nickname_idx unique (u_nickname);
+
+create index idx_user_nickname_idx on o_user (u_nickname);
\ No newline at end of file
diff --git a/src/main/resources/database/mysql/setupDatabase.sql b/src/main/resources/database/mysql/setupDatabase.sql
index 5e4256bc4fad84cc81aee400509986a46da24a4a..e984092b5f84916ade8626b97092917718de523b 100644
--- a/src/main/resources/database/mysql/setupDatabase.sql
+++ b/src/main/resources/database/mysql/setupDatabase.sql
@@ -3565,6 +3565,7 @@ alter table o_bs_identity_to_identity add constraint id_to_role_idx foreign key
 create index usr_notification_interval_idx on o_user (notification_interval);
 create index idx_user_firstname_idx on o_user (u_firstname);
 create index idx_user_lastname_idx on o_user (u_lastname);
+create index idx_user_nickname_idx on o_user (u_nickname);
 create index idx_user_email_idx on o_user (u_email);
 create index idx_user_instname_idx on o_user (u_institutionalname);
 create index idx_user_instid_idx on o_user (u_institutionaluseridentifier);
diff --git a/src/main/resources/database/oracle/alter_15_2_x_to_15_2_1.sql b/src/main/resources/database/oracle/alter_15_2_x_to_15_2_1.sql
new file mode 100644
index 0000000000000000000000000000000000000000..d721bdb78d00a31d2c0e3662466ae91a6b996c61
--- /dev/null
+++ b/src/main/resources/database/oracle/alter_15_2_x_to_15_2_1.sql
@@ -0,0 +1,3 @@
+alter table o_user add constraint iuni_user_nickname_idx unique (u_nickname);
+
+create index idx_user_nickname_idx on o_user (u_nickname);
\ No newline at end of file
diff --git a/src/main/resources/database/oracle/setupDatabase.sql b/src/main/resources/database/oracle/setupDatabase.sql
index 30d2e6129cbfed22381c847b50403d0dc366fb38..dfbb97b32b4b22ab4a1ec6a4496c0118bfa58616 100644
--- a/src/main/resources/database/oracle/setupDatabase.sql
+++ b/src/main/resources/database/oracle/setupDatabase.sql
@@ -3525,6 +3525,7 @@ create index idx_id_to_id_role_idx on o_bs_identity_to_identity (fk_role_id);
 create index usr_notification_interval_idx on o_user (notification_interval);
 create index idx_user_firstname_idx on o_user (u_firstname);
 create index idx_user_lastname_idx on o_user (u_lastname);
+create index idx_user_nickname_idx on o_user (u_nickname);
 create index idx_user_email_idx on o_user (u_email);
 create index idx_user_instname_idx on o_user (u_institutionalname);
 create index idx_user_instid_idx on o_user (u_institutionaluseridentifier);
diff --git a/src/main/resources/database/postgresql/alter_15_2_x_to_15_2_1.sql b/src/main/resources/database/postgresql/alter_15_2_x_to_15_2_1.sql
new file mode 100644
index 0000000000000000000000000000000000000000..8952f15d73f9744c916bcc585123d4173d8829a7
--- /dev/null
+++ b/src/main/resources/database/postgresql/alter_15_2_x_to_15_2_1.sql
@@ -0,0 +1,4 @@
+alter table o_user add constraint iuni_user_nickname_idx unique (u_nickname);
+
+create index idx_user_nickname_idx on o_user (u_nickname);
+create index xx_idx_nickname_low_text on o_user(lower(u_nickname) text_pattern_ops);
\ No newline at end of file
diff --git a/src/main/resources/database/postgresql/setupDatabase.sql b/src/main/resources/database/postgresql/setupDatabase.sql
index 3fa447c61e9be7c15f9a68d9b225c0aa60b8228f..b8b3c7455e2303ef74818b50a3c1e62ef79e1f2e 100644
--- a/src/main/resources/database/postgresql/setupDatabase.sql
+++ b/src/main/resources/database/postgresql/setupDatabase.sql
@@ -3407,6 +3407,7 @@ create index idx_id_to_id_role_idx on o_bs_identity_to_identity (fk_role_id);
 create index usr_notification_interval_idx on o_user (notification_interval);
 create index idx_user_firstname_idx on o_user (u_firstname);
 create index idx_user_lastname_idx on o_user (u_lastname);
+create index idx_user_nickname_idx on o_user (u_nickname);
 create index idx_user_email_idx on o_user (u_email);
 create index idx_user_instname_idx on o_user (u_institutionalname);
 create index idx_user_instid_idx on o_user (u_institutionaluseridentifier);
@@ -3416,6 +3417,7 @@ create index idx_user_creationdate_idx on o_user (creationdate);
 create index xx_idx_email_low_text on o_user(lower(u_email) text_pattern_ops);
 create index xx_idx_institutionalemail_low_text on o_user(lower(u_institutionalemail) text_pattern_ops);
 create index xx_idx_username_low_text on o_bs_identity(lower(name) text_pattern_ops);
+create index xx_idx_nickname_low_text on o_user(lower(u_nickname) text_pattern_ops);
 
 create index propvalue_idx on o_userproperty (propvalue);
 
diff --git a/src/test/java/org/olat/basesecurity/manager/IdentityDAOTest.java b/src/test/java/org/olat/basesecurity/manager/IdentityDAOTest.java
index 6b1035bcd1c7263efa599100cee5280246e59922..bb5c1d911087a51e4384ad64e31c35b45575a0ba 100644
--- a/src/test/java/org/olat/basesecurity/manager/IdentityDAOTest.java
+++ b/src/test/java/org/olat/basesecurity/manager/IdentityDAOTest.java
@@ -26,6 +26,7 @@ import org.junit.Assert;
 import org.junit.Test;
 import org.olat.basesecurity.model.FindNamedIdentity;
 import org.olat.core.id.Identity;
+import org.olat.core.id.UserConstants;
 import org.olat.test.JunitTestHelper;
 import org.olat.test.JunitTestHelper.IdentityWithLogin;
 import org.olat.test.OlatTestCase;
@@ -87,5 +88,16 @@ public class IdentityDAOTest extends OlatTestCase {
 		Assert.assertNotNull(loadedIdentity);
 		Assert.assertEquals(identity.getIdentity(), loadedIdentity);
 	}
+	
+	@Test
+	public void findIdentityByNickName() {
+		IdentityWithLogin identity = JunitTestHelper.createAndPersistRndUser("id-dao-3");
+		String nickName = identity.getIdentity().getUser().getProperty(UserConstants.NICKNAME, null);
+		
+		List<Identity> loadedIdentities = identityDao.findIdentitiesByNickName(nickName);
+		Assert.assertNotNull(loadedIdentities);
+		Assert.assertEquals(1, loadedIdentities.size());
+		Assert.assertEquals(identity.getIdentity(), loadedIdentities.get(0));
+	}
 
 }