Local user can't login when ldap error

Closes #43639

Signed-off-by: Martin Kanis <mkanis@redhat.com>
This commit is contained in:
Martin Kanis
2025-11-07 12:14:49 +01:00
committed by Pedro Igor
parent 36011008e8
commit c28cde359c
4 changed files with 151 additions and 3 deletions

View File

@@ -21,18 +21,24 @@ import org.junit.Rule;
import org.junit.Test;
import org.keycloak.component.ComponentModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.LDAPConstants;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserModel;
import org.keycloak.testsuite.arquillian.annotation.ModelTest;
import org.keycloak.testsuite.pages.AppPage;
import org.keycloak.testsuite.util.LDAPRule;
import org.keycloak.testsuite.util.LDAPTestConfiguration;
import org.keycloak.testsuite.util.LDAPTestUtils;
import org.keycloak.testsuite.util.UserBuilder;
import org.keycloak.representations.idm.UserRepresentation;
import org.keycloak.testsuite.admin.ApiUtil;
import org.keycloak.storage.ldap.LDAPStorageProvider;
import org.keycloak.storage.ldap.idm.model.LDAPObject;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Stream;
/**
@@ -104,4 +110,74 @@ public class UserStorageGracefulDegradationLdapTest extends AbstractLDAPTest {
session.users().removeUser(realm, localUser);
}
}
@Test
public void testLoginWithEmbeddedLDAPFailure() {
// Get original URL first
String originalUrl = ldapRule.getConfig().get(LDAPConstants.CONNECTION_URL);
AtomicReference<String> userIdRef = new AtomicReference<>();
try {
// First create a dedicated LDAP user
testingClient.server().run(session -> {
RealmModel realm = session.realms().getRealm("test");
ComponentModel ldapModel = LDAPTestUtils.getLdapProviderModel(realm);
LDAPStorageProvider ldapProvider = LDAPTestUtils.getLdapProvider(session, ldapModel);
// Create LDAP user for testing
LDAPObject testLdapUser = LDAPTestUtils.addLDAPUser(ldapProvider, realm, "testldapuser", "Test", "LdapUser", "testldap@example.com", null, "12345");
LDAPTestUtils.updateLDAPPassword(ldapProvider, testLdapUser, "TestPassword123!");
});
// Break LDAP connection and disable sync
testingClient.server().run(session -> {
RealmModel realm = session.realms().getRealm("test");
ComponentModel ldapModel = LDAPTestUtils.getLdapProviderModel(realm);
ldapModel.getConfig().putSingle("connectionUrl", "ldap://invalid-server:999");
ldapModel.getConfig().putSingle("syncRegistrations", "false");
ldapModel.getConfig().putSingle("importEnabled", "false");
realm.updateComponent(ldapModel);
});
// Create local user with @ in username
UserRepresentation localUser = UserBuilder.create()
.username("user@domain.com")
.password("password")
.enabled(true)
.build();
String userId = ApiUtil.getCreatedId(testRealm().users().create(localUser));
userIdRef.set(userId);
// Test that LDAP users fail to login when LDAP is down
loginPage.open();
loginPage.login("testldapuser", "TestPassword123!");
// Should stay on login page with error since LDAP user can't be authenticated
Assert.assertTrue("Should stay on login page when LDAP user login fails",
loginPage.isCurrent());
// Now try to login with the local user - this should work despite LDAP being down
loginPage.login("user@domain.com", "password");
// Should succeed despite LDAP failure
appPage.assertCurrent();
Assert.assertEquals(AppPage.RequestType.AUTH_RESPONSE, appPage.getRequestType());
} finally {
// Cleanup
testingClient.server().run(session -> {
RealmModel realm = session.realms().getRealm("test");
ComponentModel ldapModel = LDAPTestUtils.getLdapProviderModel(realm);
ldapModel.getConfig().putSingle("connectionUrl", originalUrl);
ldapModel.getConfig().putSingle("syncRegistrations", "true");
ldapModel.getConfig().putSingle("importEnabled", "true");
realm.updateComponent(ldapModel);
LDAPStorageProvider ldapProvider = LDAPTestUtils.getLdapProvider(session, ldapModel);
LDAPTestUtils.removeLDAPUserByUsername(ldapProvider, realm, ldapProvider.getLdapIdentityStore().getConfig(), "testldapuser");
});
testRealm().users().get(userIdRef.get()).remove();
}
}
}