Skip to content

Commit

Permalink
Create a new logout session when initiating it for another client
Browse files Browse the repository at this point in the history
Closes keycloak#34207

Signed-off-by: rmartinc <[email protected]>
(cherry picked from commit e41553b)
  • Loading branch information
rmartinc authored and mposolda committed Dec 3, 2024
1 parent e586829 commit 68d9798
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,7 @@ public Response logout(@QueryParam(OIDCLoginProtocol.ID_TOKEN_HINT) String encod
}
}

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);
if (uiLocales != null) {
logoutSession.setClientNote(LocaleSelectorProvider.CLIENT_REQUEST_LOCALE, uiLocales);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -306,7 +306,7 @@ public static BackchannelLogoutResponse backchannelLogout(KeycloakSession sessio

final AuthenticationSessionManager asm = new AuthenticationSessionManager(session);
AuthenticationSessionModel logoutAuthSession =
createOrJoinLogoutSession(session, realm, asm, userSession, false);
createOrJoinLogoutSession(session, realm, asm, userSession, false, false);

boolean userSessionOnlyHasLoggedOutClients = false;
try {
Expand Down Expand Up @@ -341,7 +341,8 @@ public static BackchannelLogoutResponse backchannelLogout(KeycloakSession sessio
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();
if (logoutSession != null && AuthenticationSessionModel.Action.LOGGING_OUT.name().equals(logoutSession.getAction())) {
return logoutSession;
Expand Down Expand Up @@ -384,14 +385,24 @@ public static AuthenticationSessionModel createOrJoinLogoutSession(KeycloakSessi
.filter( authSession -> AuthenticationSessionModel.Action.LOGGING_OUT.name().equals(authSession.getAction()))
.findFirst();

AuthenticationSessionModel logoutAuthSession;
AuthenticationSessionModel logoutAuthSession = null, prevAuthSession = null;
if (found.isPresent()) {
logoutAuthSession = found.get();
logger.tracef("Found existing logout session for client '%s'. Authentication session id: %s", client.getClientId(), rootLogoutSession.getId());
} else {
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());
}
}

if (logoutAuthSession == null) {
logoutAuthSession = rootLogoutSession.createAuthenticationSession(client);
logoutAuthSession.setAction(AuthenticationSessionModel.Action.LOGGING_OUT.name());
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().setClient(client);
Expand Down Expand Up @@ -658,7 +669,7 @@ public static Response browserLogout(KeycloakSession 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 initiatingIdp = logoutAuthSession.getAuthNote(AuthenticationManager.LOGOUT_INITIATING_IDP);
Expand Down Expand Up @@ -696,7 +707,7 @@ private static Response browserLogoutAllClients(UserSessionModel userSession, Ke

public static Response finishBrowserLogout(KeycloakSession session, RealmModel realm, UserSessionModel userSession, UriInfo uriInfo, ClientConnection connection, HttpHeaders headers) {
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);
if (response != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -684,7 +684,13 @@ public void logoutWithClientIdAndExpiredCode() throws IOException {
public void logoutWithClientIdAndWithoutIdTokenHint() {
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);

// Assert logout confirmation page as id_token_hint was not sent. Session still exists. Assert default language on logout page (English)
Expand Down

0 comments on commit 68d9798

Please sign in to comment.