Create a new logout session when initiating it for another client

Closes #34207

Signed-off-by: rmartinc <rmartinc@redhat.com>
This commit is contained in:
rmartinc 2024-10-23 16:00:16 +02:00 committed by Marek Posolda
parent ca6a1bfebf
commit e41553bcfb
3 changed files with 27 additions and 10 deletions

View file

@ -231,7 +231,7 @@ public class LogoutEndpoint {
} }
} }
AuthenticationSessionModel logoutSession = AuthenticationManager.createOrJoinLogoutSession(session, realm, new AuthenticationSessionManager(session), null, true); AuthenticationSessionModel logoutSession = AuthenticationManager.createOrJoinLogoutSession(session, realm, new AuthenticationSessionManager(session), null, true, true);
session.getContext().setAuthenticationSession(logoutSession); session.getContext().setAuthenticationSession(logoutSession);
if (uiLocales != null) { if (uiLocales != null) {
logoutSession.setClientNote(LocaleSelectorProvider.CLIENT_REQUEST_LOCALE, uiLocales); logoutSession.setClientNote(LocaleSelectorProvider.CLIENT_REQUEST_LOCALE, uiLocales);

View file

@ -306,7 +306,7 @@ public class AuthenticationManager {
final AuthenticationSessionManager asm = new AuthenticationSessionManager(session); final AuthenticationSessionManager asm = new AuthenticationSessionManager(session);
AuthenticationSessionModel logoutAuthSession = AuthenticationSessionModel logoutAuthSession =
createOrJoinLogoutSession(session, realm, asm, userSession, false); createOrJoinLogoutSession(session, realm, asm, userSession, false, false);
boolean userSessionOnlyHasLoggedOutClients = false; boolean userSessionOnlyHasLoggedOutClients = false;
try { try {
@ -341,7 +341,8 @@ public class AuthenticationManager {
return backchannelLogoutResponse; return backchannelLogoutResponse;
} }
public static AuthenticationSessionModel createOrJoinLogoutSession(KeycloakSession session, RealmModel realm, final AuthenticationSessionManager asm, UserSessionModel userSession, boolean browserCookie) { public static AuthenticationSessionModel createOrJoinLogoutSession(KeycloakSession session, RealmModel realm,
final AuthenticationSessionManager asm, UserSessionModel userSession, boolean browserCookie, boolean initiateLogout) {
AuthenticationSessionModel logoutSession = session.getContext().getAuthenticationSession(); AuthenticationSessionModel logoutSession = session.getContext().getAuthenticationSession();
if (logoutSession != null && AuthenticationSessionModel.Action.LOGGING_OUT.name().equals(logoutSession.getAction())) { if (logoutSession != null && AuthenticationSessionModel.Action.LOGGING_OUT.name().equals(logoutSession.getAction())) {
return logoutSession; return logoutSession;
@ -384,14 +385,24 @@ public class AuthenticationManager {
.filter( authSession -> AuthenticationSessionModel.Action.LOGGING_OUT.name().equals(authSession.getAction())) .filter( authSession -> AuthenticationSessionModel.Action.LOGGING_OUT.name().equals(authSession.getAction()))
.findFirst(); .findFirst();
AuthenticationSessionModel logoutAuthSession; AuthenticationSessionModel logoutAuthSession = null, prevAuthSession = null;
if (found.isPresent()) { if (found.isPresent()) {
logoutAuthSession = found.get(); prevAuthSession = found.get();
if (!initiateLogout || client.getId().equals(prevAuthSession.getClient().getId())) {
logoutAuthSession = prevAuthSession;
logger.tracef("Found existing logout session for client '%s'. Authentication session id: %s", client.getClientId(), rootLogoutSession.getId()); logger.tracef("Found existing logout session for client '%s'. Authentication session id: %s", client.getClientId(), rootLogoutSession.getId());
} else { }
}
if (logoutAuthSession == null) {
logoutAuthSession = rootLogoutSession.createAuthenticationSession(client); logoutAuthSession = rootLogoutSession.createAuthenticationSession(client);
logoutAuthSession.setAction(AuthenticationSessionModel.Action.LOGGING_OUT.name()); logoutAuthSession.setAction(AuthenticationSessionModel.Action.LOGGING_OUT.name());
logger.tracef("Creating logout session for client '%s'. Authentication session id: %s", client.getClientId(), rootLogoutSession.getId()); logger.tracef("Creating logout session for client '%s'. Authentication session id: %s", client.getClientId(), rootLogoutSession.getId());
if (prevAuthSession != null) {
// remove previous logout session for the other client
rootLogoutSession.removeAuthenticationSessionByTabId(prevAuthSession.getTabId());
logger.tracef("Removing previous logout session for client '%s' in %s", prevAuthSession.getClient().getClientId(), rootLogoutSession.getId());
}
} }
session.getContext().setAuthenticationSession(logoutAuthSession); session.getContext().setAuthenticationSession(logoutAuthSession);
session.getContext().setClient(client); session.getContext().setClient(client);
@ -658,7 +669,7 @@ public class AuthenticationManager {
} }
final AuthenticationSessionManager asm = new AuthenticationSessionManager(session); final AuthenticationSessionManager asm = new AuthenticationSessionManager(session);
AuthenticationSessionModel logoutAuthSession = createOrJoinLogoutSession(session, realm, asm, userSession, true); AuthenticationSessionModel logoutAuthSession = createOrJoinLogoutSession(session, realm, asm, userSession, true, false);
String brokerId = userSession.getNote(Details.IDENTITY_PROVIDER); String brokerId = userSession.getNote(Details.IDENTITY_PROVIDER);
String initiatingIdp = logoutAuthSession.getAuthNote(AuthenticationManager.LOGOUT_INITIATING_IDP); String initiatingIdp = logoutAuthSession.getAuthNote(AuthenticationManager.LOGOUT_INITIATING_IDP);
@ -696,7 +707,7 @@ public class AuthenticationManager {
public static Response finishBrowserLogout(KeycloakSession session, RealmModel realm, UserSessionModel userSession, UriInfo uriInfo, ClientConnection connection, HttpHeaders headers) { public static Response finishBrowserLogout(KeycloakSession session, RealmModel realm, UserSessionModel userSession, UriInfo uriInfo, ClientConnection connection, HttpHeaders headers) {
final AuthenticationSessionManager asm = new AuthenticationSessionManager(session); final AuthenticationSessionManager asm = new AuthenticationSessionManager(session);
AuthenticationSessionModel logoutAuthSession = createOrJoinLogoutSession(session, realm, asm, userSession, true); AuthenticationSessionModel logoutAuthSession = createOrJoinLogoutSession(session, realm, asm, userSession, true, false);
Response response = browserLogoutAllClients(userSession, session, realm, headers, uriInfo, logoutAuthSession); Response response = browserLogoutAllClients(userSession, session, realm, headers, uriInfo, logoutAuthSession);
if (response != null) { if (response != null) {

View file

@ -684,7 +684,13 @@ public class RPInitiatedLogoutTest extends AbstractTestRealmKeycloakTest {
public void logoutWithClientIdAndWithoutIdTokenHint() { public void logoutWithClientIdAndWithoutIdTokenHint() {
OAuthClient.AccessTokenResponse tokenResponse = loginUser(); OAuthClient.AccessTokenResponse tokenResponse = loginUser();
String logoutUrl = oauth.getLogoutUrl().postLogoutRedirectUri(APP_REDIRECT_URI).clientId("test-app").state("somethingg").build(); // logout url with no parameters, client is the account app
String logoutUrl = oauth.getLogoutUrl().build();
driver.navigate().to(logoutUrl);
logoutConfirmPage.assertCurrent();
// change logout to our app with redirect uri
logoutUrl = oauth.getLogoutUrl().postLogoutRedirectUri(APP_REDIRECT_URI).clientId("test-app").state("somethingg").build();
driver.navigate().to(logoutUrl); driver.navigate().to(logoutUrl);
// Assert logout confirmation page as id_token_hint was not sent. Session still exists. Assert default language on logout page (English) // Assert logout confirmation page as id_token_hint was not sent. Session still exists. Assert default language on logout page (English)