diff --git a/integration/spring-security/src/main/java/org/keycloak/adapters/springsecurity/authentication/KeycloakLogoutHandler.java b/integration/spring-security/src/main/java/org/keycloak/adapters/springsecurity/authentication/KeycloakLogoutHandler.java
index 6a64765..d843aa7 100644
--- a/integration/spring-security/src/main/java/org/keycloak/adapters/springsecurity/authentication/KeycloakLogoutHandler.java
+++ b/integration/spring-security/src/main/java/org/keycloak/adapters/springsecurity/authentication/KeycloakLogoutHandler.java
@@ -6,15 +6,12 @@ import org.keycloak.adapters.springsecurity.AdapterDeploymentContextBean;
import org.keycloak.adapters.springsecurity.token.KeycloakAuthenticationToken;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import org.springframework.security.authentication.AnonymousAuthenticationToken;
import org.springframework.security.core.Authentication;
-import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.logout.LogoutHandler;
import org.springframework.util.Assert;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
-import java.io.IOException;
/**
* Logs the current user out of Keycloak.
@@ -36,29 +33,17 @@ public class KeycloakLogoutHandler implements LogoutHandler {
@Override
public void logout(HttpServletRequest request, HttpServletResponse response, Authentication authentication) {
- if (authentication instanceof AnonymousAuthenticationToken) {
- log.warn("Attempt to log out an anonymous authentication");
+ if (!KeycloakAuthenticationToken.class.isAssignableFrom(authentication.getClass())) {
+ log.warn("Cannot log out a non-Keycloak authentication: {}", authentication);
return;
}
- try {
- handleSingleSignOut(request, response);
- } catch (IOException e) {
- throw new IllegalStateException("Unable to make logout admin request!", e);
- }
-
+ handleSingleSignOut(request, response, (KeycloakAuthenticationToken) authentication);
}
- protected void handleSingleSignOut(HttpServletRequest request, HttpServletResponse response) throws IOException {
-
- KeycloakAuthenticationToken authentication = (KeycloakAuthenticationToken) SecurityContextHolder.getContext().getAuthentication();
+ protected void handleSingleSignOut(HttpServletRequest request, HttpServletResponse response, KeycloakAuthenticationToken authenticationToken) {
KeycloakDeployment deployment = deploymentContextBean.getDeployment();
- RefreshableKeycloakSecurityContext session = (RefreshableKeycloakSecurityContext) authentication.getAccount().getKeycloakSecurityContext();
-
- try {
- session.logout(deployment);
- } catch (Exception e) {
- log.error("Unable to complete Keycloak single sign out", e);
- }
+ RefreshableKeycloakSecurityContext session = (RefreshableKeycloakSecurityContext) authenticationToken.getAccount().getKeycloakSecurityContext();
+ session.logout(deployment);
}
}
diff --git a/integration/spring-security/src/test/java/org/keycloak/adapters/springsecurity/authentication/KeycloakLogoutHandlerTest.java b/integration/spring-security/src/test/java/org/keycloak/adapters/springsecurity/authentication/KeycloakLogoutHandlerTest.java
new file mode 100644
index 0000000..2ee32af
--- /dev/null
+++ b/integration/spring-security/src/test/java/org/keycloak/adapters/springsecurity/authentication/KeycloakLogoutHandlerTest.java
@@ -0,0 +1,96 @@
+package org.keycloak.adapters.springsecurity.authentication;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.keycloak.adapters.KeycloakAccount;
+import org.keycloak.adapters.KeycloakDeployment;
+import org.keycloak.adapters.RefreshableKeycloakSecurityContext;
+import org.keycloak.adapters.springsecurity.AdapterDeploymentContextBean;
+import org.keycloak.adapters.springsecurity.account.KeycloakRole;
+import org.keycloak.adapters.springsecurity.token.KeycloakAuthenticationToken;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.springframework.mock.web.MockHttpServletRequest;
+import org.springframework.mock.web.MockHttpServletResponse;
+import org.springframework.security.authentication.AnonymousAuthenticationToken;
+import org.springframework.security.authentication.RememberMeAuthenticationToken;
+import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import org.springframework.security.core.Authentication;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.UUID;
+
+import static org.mockito.Mockito.*;
+
+/**
+ * Keycloak logout handler tests.
+ */
+public class KeycloakLogoutHandlerTest {
+
+ private KeycloakAuthenticationToken keycloakAuthenticationToken;
+ private KeycloakLogoutHandler keycloakLogoutHandler;
+
+ private MockHttpServletRequest request;
+ private MockHttpServletResponse response;
+
+ @Mock
+ private AdapterDeploymentContextBean adapterDeploymentContextBean;
+
+ @Mock
+ private KeycloakAccount keycloakAccount;
+
+ @Mock
+ private KeycloakDeployment keycloakDeployment;
+
+ @Mock
+ private RefreshableKeycloakSecurityContext session;
+
+ private Collection<KeycloakRole> authorities = Collections.singleton(new KeycloakRole(UUID.randomUUID().toString()));
+
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+ keycloakAuthenticationToken = mock(KeycloakAuthenticationToken.class);
+ keycloakLogoutHandler = new KeycloakLogoutHandler(adapterDeploymentContextBean);
+ request = new MockHttpServletRequest();
+ response = new MockHttpServletResponse();
+
+ when(adapterDeploymentContextBean.getDeployment()).thenReturn(keycloakDeployment);
+ when(keycloakAuthenticationToken.getAccount()).thenReturn(keycloakAccount);
+ when(keycloakAccount.getKeycloakSecurityContext()).thenReturn(session);
+ }
+
+ @Test
+ public void testLogout() throws Exception {
+ keycloakLogoutHandler.logout(request, response, keycloakAuthenticationToken);
+ verify(session).logout(eq(keycloakDeployment));
+ }
+
+ @Test
+ public void testLogoutAnonymousAuthentication() throws Exception {
+ Authentication authentication = new AnonymousAuthenticationToken(UUID.randomUUID().toString(), UUID.randomUUID().toString(), authorities);
+ keycloakLogoutHandler.logout(request, response, authentication);
+ verifyZeroInteractions(session);
+ }
+
+ @Test
+ public void testLogoutUsernamePasswordAuthentication() throws Exception {
+ Authentication authentication = new UsernamePasswordAuthenticationToken(UUID.randomUUID().toString(), UUID.randomUUID().toString(), authorities);
+ keycloakLogoutHandler.logout(request, response, authentication);
+ verifyZeroInteractions(session);
+ }
+
+ @Test
+ public void testLogoutRememberMeAuthentication() throws Exception {
+ Authentication authentication = new RememberMeAuthenticationToken(UUID.randomUUID().toString(), UUID.randomUUID().toString(), authorities);
+ keycloakLogoutHandler.logout(request, response, authentication);
+ verifyZeroInteractions(session);
+ }
+
+ @Test
+ public void testHandleSingleSignOut() throws Exception {
+ keycloakLogoutHandler.handleSingleSignOut(request, response, keycloakAuthenticationToken);
+ verify(session).logout(eq(keycloakDeployment));
+ }
+}