keycloak-uncached

Merge pull request #1353 from Smartling/KEYCLOAK-1438 Fix

6/12/2015 3:50:00 AM

Details

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));
+    }
+}