Add null checks after retrieving user from LDAP for validation to prevent NPE when user is removed in LDAP.
Closes #28523 Signed-off-by: Stefan Guilhen <sguilhen@redhat.com>
This commit is contained in:
parent
d31f128ca2
commit
e6b9d287af
2 changed files with 37 additions and 1 deletions
|
@ -790,6 +790,10 @@ public class LDAPStorageProvider implements UserStorageProvider,
|
|||
} else {
|
||||
// Use Naming LDAP API
|
||||
LDAPObject ldapUser = loadAndValidateUser(realm, user);
|
||||
if (ldapUser == null) {
|
||||
// user was removed from ldap - password verification must fail.
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
ldapIdentityStore.validatePassword(ldapUser, password);
|
||||
|
@ -821,6 +825,10 @@ public class LDAPStorageProvider implements UserStorageProvider,
|
|||
LDAPIdentityStore ldapIdentityStore = getLdapIdentityStore();
|
||||
String password = input.getChallengeResponse();
|
||||
LDAPObject ldapUser = loadAndValidateUser(realm, user);
|
||||
if (ldapUser == null) {
|
||||
logger.warnf("User '%s' can't be updated in LDAP as it doesn't exist there", user.getUsername());
|
||||
return false;
|
||||
}
|
||||
if (ldapIdentityStore.getConfig().isValidatePasswordPolicy()) {
|
||||
PolicyError error = session.getProvider(PasswordPolicyManagerProvider.class).validate(realm, user, password);
|
||||
if (error != null) throw new ModelException(error.getMessage(), error.getParameters());
|
||||
|
@ -967,7 +975,8 @@ public class LDAPStorageProvider implements UserStorageProvider,
|
|||
return null;
|
||||
} else {
|
||||
LDAPObject ldapObject = loadAndValidateUser(realm, user);
|
||||
if (kerberosPrincipalAttrName != null && !kerberosPrincipal.toString().equalsIgnoreCase(ldapObject.getAttributeAsString(kerberosPrincipalAttrName))) {
|
||||
if (kerberosPrincipalAttrName != null && ldapObject != null &&
|
||||
!kerberosPrincipal.toString().equalsIgnoreCase(ldapObject.getAttributeAsString(kerberosPrincipalAttrName))) {
|
||||
logger.warnf("User with username [%s] aready exists and is linked to provider [%s] but is not valid. Authenticated kerberos principal is [%s], but LDAP user has different kerberos principal [%s]",
|
||||
user.getUsername(), model.getName(), kerberosPrincipal, ldapObject.getAttributeAsString(kerberosPrincipalAttrName));
|
||||
ldapObject = null;
|
||||
|
|
|
@ -324,4 +324,31 @@ public class LDAPUserLoginTest extends AbstractLDAPTest {
|
|||
verifyConnectionUrlProtocolPrefix("ldap://");
|
||||
runLDAPLoginTest();
|
||||
}
|
||||
|
||||
// Check that login fails as expected when an LDAP user that has already authenticated is removed from LDAP and attempts to authenticate again.
|
||||
// See https://github.com/keycloak/keycloak/issues/28523
|
||||
@Test
|
||||
@LDAPConnectionParameters(bindType=LDAPConnectionParameters.BindType.SIMPLE, encryption=LDAPConnectionParameters.Encryption.NONE)
|
||||
public void loginLDAPUserAuthenticationSimpleDeleteLDAPUser() {
|
||||
// create another user for this test.
|
||||
getTestingClient().server().run(session -> {
|
||||
LDAPTestContext ctx = LDAPTestContext.init(session);
|
||||
RealmModel appRealm = ctx.getRealm();
|
||||
LDAPObject jane = LDAPTestUtils.addLDAPUser(ctx.getLdapProvider(), appRealm, "janedoe", "Jane",
|
||||
"Doe", "janedoe@keycloak.org", "2nd Avenue", "09283");
|
||||
LDAPTestUtils.updateLDAPPassword(ctx.getLdapProvider(), jane, DEFAULT_TEST_USERS.get("VALID_USER_PASSWORD"));
|
||||
});
|
||||
// login with the new user, then logout - user is now cached in Keycloak.
|
||||
this.verifyLoginSucceededAndLogout("janedoe", DEFAULT_TEST_USERS.get("VALID_USER_PASSWORD"));
|
||||
|
||||
// now remove the user directly in LDAP.
|
||||
getTestingClient().server().run(session -> {
|
||||
LDAPTestContext ctx = LDAPTestContext.init(session);
|
||||
RealmModel appRealm = ctx.getRealm();
|
||||
LDAPTestUtils.removeLDAPUserByUsername(ctx.getLdapProvider(), appRealm, ctx.getLdapProvider().getLdapIdentityStore().getConfig(), "janedoe");
|
||||
});
|
||||
|
||||
// attempt to login again with the deleted user should fail with the proper message.
|
||||
this.verifyLoginFailed("janedoe", DEFAULT_TEST_USERS.get("VALID_USER_PASSWORD"));
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue