Steps to reproduce
- Create a user with mixed case sensitivity such as "Horatio Nelson" in LDAP
- Hook Confluence to the LDAP directory via Internal with LDAP Authentication (Delegated)
- Login first as "Horatio Nelson" (to create the user as "Horatio Nelson" in the cwd_user table)
- Logout, then login again as "horatio nelson" (all lowercase)
You will get this error in Confluence (JIRA is working fine, more about it below):
2013-10-11 22:19:58,407 ERROR [http-8443-6] [[Standalone].[localhost].[/c530].[action]] log Servlet.service() for servlet action threw exception
java.lang.IllegalStateException: Unable to rename user Horatio Nelson to horatio nelson
at com.atlassian.crowd.directory.AbstractInternalDirectory.forceRenameUser(AbstractInternalDirectory.java:611)
at com.atlassian.crowd.directory.DelegatedAuthenticationDirectory.authenticateAndUpdateOrCreate(DelegatedAuthenticationDirectory.java:218)
at com.atlassian.crowd.directory.DelegatedAuthenticationDirectory.authenticate(DelegatedAuthenticationDirectory.java:175)
Cause:
The problem is caused by this function in com.atlassian.crowd.directory.DelegatedAuthenticationDirectory.java:
private User authenticateAndUpdateOrCreate(String name, PasswordCredential credential)
throws InactiveAccountException, ExpiredCredentialException, OperationFailedException, InvalidAuthenticationException, UserNotFoundException
{
User ldapUser = ldapDirectory.authenticate(name, credential);
User internalUser = findLocalUserByExternalId(ldapUser.getExternalId());
if (internalUser != null)
{
if (!internalUser.getName().equals(name))
{
if (isUserUpdateOnAuthEnabled())
{
try
{
internalUser = internalDirectory.forceRenameUser(internalUser, name);
}
catch (UserNotFoundException e)
{
throw new ConcurrentModificationException("Unable to rename '" + internalUser.getName() + "' to new name '" + name + "' during login.");
}
}
Specifically, this if statement:
if (!internalUser.getName().equals(name))
Which takes the name string directly from the user input, and comparing it to the username stored in cwd_user directly, hence, the mismatch, which is why forceRenameUser is called in the first place
So far, this affects any Confluence distribution bundled with the Crowd 2.7 integration libraries
Description update: