Logout from all clients after IdP logout is performed
Closes #25234 Signed-off-by: rmartinc <rmartinc@redhat.com>
This commit is contained in:
parent
22da43c619
commit
7d05a7a013
3 changed files with 59 additions and 10 deletions
|
@ -645,16 +645,11 @@ 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);
|
||||||
|
|
||||||
Response response = browserLogoutAllClients(userSession, session, realm, headers, uriInfo, logoutAuthSession);
|
|
||||||
if (response != null) {
|
|
||||||
return response;
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
||||||
if (brokerId != null && !brokerId.equals(initiatingIdp)) {
|
if (brokerId != null && !brokerId.equals(initiatingIdp)) {
|
||||||
IdentityProvider identityProvider = IdentityBrokerService.getIdentityProvider(session, realm, brokerId);
|
IdentityProvider identityProvider = IdentityBrokerService.getIdentityProvider(session, realm, brokerId);
|
||||||
response = identityProvider.keycloakInitiatedBrowserLogout(session, userSession, uriInfo, realm);
|
Response response = identityProvider.keycloakInitiatedBrowserLogout(session, userSession, uriInfo, realm);
|
||||||
if (response != null) {
|
if (response != null) {
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
@ -688,6 +683,11 @@ 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);
|
||||||
|
|
||||||
|
Response response = browserLogoutAllClients(userSession, session, realm, headers, uriInfo, logoutAuthSession);
|
||||||
|
if (response != null) {
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
checkUserSessionOnlyHasLoggedOutClients(realm, userSession, logoutAuthSession);
|
checkUserSessionOnlyHasLoggedOutClients(realm, userSession, logoutAuthSession);
|
||||||
|
|
||||||
// For resolving artifact we don't need any cookie, all details are stored in session storage so we can remove
|
// For resolving artifact we don't need any cookie, all details are stored in session storage so we can remove
|
||||||
|
@ -703,7 +703,7 @@ public class AuthenticationManager {
|
||||||
.setEventBuilder(event);
|
.setEventBuilder(event);
|
||||||
|
|
||||||
|
|
||||||
Response response = protocol.finishBrowserLogout(userSession, logoutAuthSession);
|
response = protocol.finishBrowserLogout(userSession, logoutAuthSession);
|
||||||
|
|
||||||
// It may be possible that there are some client sessions that are still in LOGGING_OUT state
|
// It may be possible that there are some client sessions that are still in LOGGING_OUT state
|
||||||
long numberOfUnconfirmedSessions = userSession.getAuthenticatedClientSessions().values().stream()
|
long numberOfUnconfirmedSessions = userSession.getAuthenticatedClientSessions().values().stream()
|
||||||
|
|
|
@ -342,7 +342,7 @@ public abstract class AbstractBaseBrokerTest extends AbstractKeycloakTest {
|
||||||
.clientId(clientId)
|
.clientId(clientId)
|
||||||
.initiatingIdp(initiatingIdp);
|
.initiatingIdp(initiatingIdp);
|
||||||
|
|
||||||
if (clientId != null || idTokenHint != null) {
|
if (redirectUri != null && (clientId != null || idTokenHint != null)) {
|
||||||
builder.postLogoutRedirectUri(encodeUrl(redirectUri));
|
builder.postLogoutRedirectUri(encodeUrl(redirectUri));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package org.keycloak.testsuite.broker;
|
package org.keycloak.testsuite.broker;
|
||||||
|
|
||||||
|
import org.junit.Assert;
|
||||||
import org.junit.Rule;
|
import org.junit.Rule;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.keycloak.OAuth2Constants;
|
import org.keycloak.OAuth2Constants;
|
||||||
|
@ -8,11 +9,14 @@ import org.keycloak.admin.client.resource.IdentityProviderResource;
|
||||||
import org.keycloak.admin.client.resource.RealmResource;
|
import org.keycloak.admin.client.resource.RealmResource;
|
||||||
import org.keycloak.common.VerificationException;
|
import org.keycloak.common.VerificationException;
|
||||||
import org.keycloak.cookie.CookieType;
|
import org.keycloak.cookie.CookieType;
|
||||||
|
import org.keycloak.protocol.oidc.OIDCConfigAttributes;
|
||||||
import org.keycloak.representations.IDToken;
|
import org.keycloak.representations.IDToken;
|
||||||
import org.keycloak.representations.idm.IdentityProviderRepresentation;
|
import org.keycloak.representations.idm.IdentityProviderRepresentation;
|
||||||
import org.keycloak.testsuite.AssertEvents;
|
import org.keycloak.testsuite.AssertEvents;
|
||||||
|
import org.keycloak.testsuite.updaters.ClientAttributeUpdater;
|
||||||
import org.keycloak.testsuite.util.AccountHelper;
|
import org.keycloak.testsuite.util.AccountHelper;
|
||||||
import org.keycloak.testsuite.util.OAuthClient;
|
import org.keycloak.testsuite.util.OAuthClient;
|
||||||
|
import org.keycloak.testsuite.util.WaitUtils;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.keycloak.testsuite.broker.BrokerTestConstants.REALM_CONS_NAME;
|
import static org.keycloak.testsuite.broker.BrokerTestConstants.REALM_CONS_NAME;
|
||||||
|
@ -22,7 +26,6 @@ import static org.keycloak.testsuite.broker.BrokerTestTools.waitForPage;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
public class KcOidcBrokerLogoutTest extends AbstractKcOidcBrokerLogoutTest {
|
public class KcOidcBrokerLogoutTest extends AbstractKcOidcBrokerLogoutTest {
|
||||||
|
|
||||||
|
@ -162,7 +165,6 @@ public class KcOidcBrokerLogoutTest extends AbstractKcOidcBrokerLogoutTest {
|
||||||
identityProviderResource.update(representation);
|
identityProviderResource.update(representation);
|
||||||
logInAsUserInIDPForFirstTime();
|
logInAsUserInIDPForFirstTime();
|
||||||
appPage.assertCurrent();
|
appPage.assertCurrent();
|
||||||
driver.manage().timeouts().pageLoadTimeout(1, TimeUnit.DAYS);
|
|
||||||
executeLogoutFromRealm(
|
executeLogoutFromRealm(
|
||||||
getConsumerRoot(),
|
getConsumerRoot(),
|
||||||
bc.consumerRealmName(),
|
bc.consumerRealmName(),
|
||||||
|
@ -231,4 +233,51 @@ public class KcOidcBrokerLogoutTest extends AbstractKcOidcBrokerLogoutTest {
|
||||||
identityProviderResource.update(representation);
|
identityProviderResource.update(representation);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFrontChannelLogoutRequestsSendingOnlyClientIdWithFrontChannelLogoutApp() throws Exception {
|
||||||
|
RealmResource realm = adminClient.realm(bc.consumerRealmName());
|
||||||
|
IdentityProviderResource identityProviderResource = realm.identityProviders().get(bc.getIDPAlias());
|
||||||
|
IdentityProviderRepresentation representation = identityProviderResource.toRepresentation();
|
||||||
|
Map<String, String> config = representation.getConfig();
|
||||||
|
Map<String, String> originalConfig = new HashMap<>(config);
|
||||||
|
|
||||||
|
try (ClientAttributeUpdater clientUpdater = ClientAttributeUpdater.forClient(adminClient, bc.consumerRealmName(), "broker-app")
|
||||||
|
.setFrontchannelLogout(true)
|
||||||
|
.setAttribute(OIDCConfigAttributes.FRONT_CHANNEL_LOGOUT_URI, getConsumerRoot() + "/auth/realms/" + bc.consumerRealmName() + "/app/logout")
|
||||||
|
.update()){
|
||||||
|
config.put("backchannelSupported", Boolean.FALSE.toString());
|
||||||
|
config.put("sendIdTokenOnLogout", Boolean.FALSE.toString());
|
||||||
|
config.put("sendClientIdOnLogout", Boolean.TRUE.toString());
|
||||||
|
identityProviderResource.update(representation);
|
||||||
|
logInAsUserInIDPForFirstTime();
|
||||||
|
appPage.assertCurrent();
|
||||||
|
executeLogoutFromRealm(
|
||||||
|
getConsumerRoot(),
|
||||||
|
bc.consumerRealmName(),
|
||||||
|
"something-else",
|
||||||
|
null,
|
||||||
|
"broker-app",
|
||||||
|
null
|
||||||
|
);
|
||||||
|
logoutConfirmPage.isCurrent();
|
||||||
|
// confirm logout at consumer
|
||||||
|
logoutConfirmPage.confirmLogout();
|
||||||
|
// confirm logout at provider
|
||||||
|
logoutConfirmPage.confirmLogout();
|
||||||
|
|
||||||
|
WaitUtils.waitForPageToLoad();
|
||||||
|
logoutConfirmPage.isCurrent();
|
||||||
|
Assert.assertTrue(driver.getPageSource().contains("You are logging out from following apps"));
|
||||||
|
Assert.assertTrue(driver.getPageSource().contains("broker-app"));
|
||||||
|
|
||||||
|
oauth.clientId("account");
|
||||||
|
oauth.redirectUri(getConsumerRoot() + "/auth/realms/" + REALM_PROV_NAME + "/account");
|
||||||
|
loginPage.open(REALM_PROV_NAME);
|
||||||
|
waitForPage(driver, "sign in to provider", true);
|
||||||
|
} finally {
|
||||||
|
representation.setConfig(originalConfig);
|
||||||
|
identityProviderResource.update(representation);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue