KEYCLOAK-9623 Disabling logged in user will not allow other user to login after he is thrown out of his session

This commit is contained in:
Martin Kanis 2020-04-14 16:51:38 +02:00 committed by Marek Posolda
parent 8513760e25
commit a04c70531a
2 changed files with 57 additions and 12 deletions

View file

@ -29,6 +29,7 @@ import org.keycloak.models.AuthenticationFlowModel;
import org.keycloak.models.ClientModel; import org.keycloak.models.ClientModel;
import org.keycloak.models.KeycloakSession; import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel; import org.keycloak.models.RealmModel;
import org.keycloak.models.UserModel;
import org.keycloak.models.UserSessionModel; import org.keycloak.models.UserSessionModel;
import org.keycloak.models.utils.AuthenticationFlowResolver; import org.keycloak.models.utils.AuthenticationFlowResolver;
import org.keycloak.protocol.LoginProtocol.Error; import org.keycloak.protocol.LoginProtocol.Error;
@ -188,16 +189,20 @@ public abstract class AuthorizationEndpointBase {
UserSessionModel userSession = userSessionCrossDCManager.getUserSessionIfExistsRemotely(manager, realm); UserSessionModel userSession = userSessionCrossDCManager.getUserSessionIfExistsRemotely(manager, realm);
if (userSession != null) { if (userSession != null) {
UserModel user = userSession.getUser();
if (user != null && !user.isEnabled()) {
authSession = createNewAuthenticationSession(manager, client);
AuthenticationManager.backchannelLogout(session, userSession, true);
} else {
String userSessionId = userSession.getId(); String userSessionId = userSession.getId();
rootAuthSession = session.authenticationSessions().createRootAuthenticationSession(userSessionId, realm); rootAuthSession = session.authenticationSessions().createRootAuthenticationSession(userSessionId, realm);
authSession = rootAuthSession.createAuthenticationSession(client); authSession = rootAuthSession.createAuthenticationSession(client);
logger.debugf("Sent request to authz endpoint. We don't have root authentication session with ID '%s' but we have userSession." + logger.debugf("Sent request to authz endpoint. We don't have root authentication session with ID '%s' but we have userSession." +
"Re-created root authentication session with same ID. Client is: %s . New authentication session tab ID: %s", userSessionId, client.getClientId(), authSession.getTabId()); "Re-created root authentication session with same ID. Client is: %s . New authentication session tab ID: %s", userSessionId, client.getClientId(), authSession.getTabId());
}
} else { } else {
rootAuthSession = manager.createAuthenticationSession(realm, true); authSession = createNewAuthenticationSession(manager, client);
authSession = rootAuthSession.createAuthenticationSession(client);
logger.debugf("Sent request to authz endpoint. Created new root authentication session with ID '%s' . Client: %s . New authentication session tab ID: %s",
rootAuthSession.getId(), client.getClientId(), authSession.getTabId());
} }
} }
@ -206,4 +211,12 @@ public abstract class AuthorizationEndpointBase {
return authSession; return authSession;
} }
private AuthenticationSessionModel createNewAuthenticationSession(AuthenticationSessionManager manager, ClientModel client) {
RootAuthenticationSessionModel rootAuthSession = manager.createAuthenticationSession(realm, true);
AuthenticationSessionModel authSession = rootAuthSession.createAuthenticationSession(client);
logger.debugf("Sent request to authz endpoint. Created new root authentication session with ID '%s' . Client: %s . New authentication session tab ID: %s",
rootAuthSession.getId(), client.getClientId(), authSession.getTabId());
return authSession;
}
} }

View file

@ -16,8 +16,6 @@
*/ */
package org.keycloak.testsuite.forms; package org.keycloak.testsuite.forms;
import java.net.MalformedURLException;
import java.net.URI;
import org.jboss.arquillian.drone.api.annotation.Drone; import org.jboss.arquillian.drone.api.annotation.Drone;
import org.jboss.arquillian.graphene.page.Page; import org.jboss.arquillian.graphene.page.Page;
import org.junit.Assert; import org.junit.Assert;
@ -33,7 +31,6 @@ import org.keycloak.events.EventType;
import org.keycloak.jose.jws.JWSInput; import org.keycloak.jose.jws.JWSInput;
import org.keycloak.jose.jws.JWSInputException; import org.keycloak.jose.jws.JWSInputException;
import org.keycloak.models.BrowserSecurityHeaders; import org.keycloak.models.BrowserSecurityHeaders;
import org.keycloak.models.Constants;
import org.keycloak.models.utils.SessionTimeoutHelper; import org.keycloak.models.utils.SessionTimeoutHelper;
import org.keycloak.protocol.oidc.OIDCLoginProtocolService; import org.keycloak.protocol.oidc.OIDCLoginProtocolService;
import org.keycloak.representations.idm.ClientRepresentation; import org.keycloak.representations.idm.ClientRepresentation;
@ -45,6 +42,7 @@ import org.keycloak.testsuite.AbstractTestRealmKeycloakTest;
import org.keycloak.testsuite.admin.ApiUtil; import org.keycloak.testsuite.admin.ApiUtil;
import org.keycloak.testsuite.arquillian.AuthServerTestEnricher; import org.keycloak.testsuite.arquillian.AuthServerTestEnricher;
import org.keycloak.testsuite.console.page.AdminConsole; import org.keycloak.testsuite.console.page.AdminConsole;
import org.keycloak.testsuite.pages.AccountUpdateProfilePage;
import org.keycloak.testsuite.pages.AppPage; import org.keycloak.testsuite.pages.AppPage;
import org.keycloak.testsuite.pages.AppPage.RequestType; import org.keycloak.testsuite.pages.AppPage.RequestType;
import org.keycloak.testsuite.pages.ErrorPage; import org.keycloak.testsuite.pages.ErrorPage;
@ -59,6 +57,7 @@ import org.keycloak.testsuite.util.Matchers;
import org.keycloak.testsuite.util.RealmBuilder; import org.keycloak.testsuite.util.RealmBuilder;
import org.keycloak.testsuite.util.TokenSignatureUtil; import org.keycloak.testsuite.util.TokenSignatureUtil;
import org.keycloak.testsuite.util.UserBuilder; import org.keycloak.testsuite.util.UserBuilder;
import org.keycloak.testsuite.util.WaitUtils;
import org.openqa.selenium.NoSuchElementException; import org.openqa.selenium.NoSuchElementException;
import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebDriver;
@ -149,6 +148,9 @@ public class LoginTest extends AbstractTestRealmKeycloakTest {
@Page @Page
protected ErrorPage errorPage; protected ErrorPage errorPage;
@Page
protected AccountUpdateProfilePage profilePage;
@Page @Page
protected LoginPasswordUpdatePage updatePasswordPage; protected LoginPasswordUpdatePage updatePasswordPage;
@ -353,6 +355,36 @@ public class LoginTest extends AbstractTestRealmKeycloakTest {
} }
} }
@Test
public void loginDifferentUserAfterDisabledUserThrownOut() {
String userId = adminClient.realm("test").users().search("test-user@localhost").get(0).getId();
try {
//profilePage.open();
loginPage.open();
loginPage.login("test-user@localhost", "password");
//accountPage.assertCurrent();
appPage.assertCurrent();
appPage.openAccount();
profilePage.assertCurrent();
setUserEnabled(userId, false);
// force refresh token which results in redirecting to login page
profilePage.updateUsername("notPermitted");
WaitUtils.waitForPageToLoad();
loginPage.assertCurrent();
// try to log in as different user
loginPage.login("keycloak-user@localhost", "password");
profilePage.assertCurrent();
} finally {
setUserEnabled(userId, true);
}
}
@Test @Test
public void loginInvalidUsername() { public void loginInvalidUsername() {
loginPage.open(); loginPage.open();