keycloak-aplcache

Merge pull request #1610 from raehalme/KEYCLOAK-1828 KEYCLOAK-1828

9/24/2015 1:32:27 AM

Details

diff --git a/integration/spring-security/src/main/java/org/keycloak/adapters/springsecurity/filter/KeycloakAuthenticationProcessingFilter.java b/integration/spring-security/src/main/java/org/keycloak/adapters/springsecurity/filter/KeycloakAuthenticationProcessingFilter.java
index 1a29a87..961a09e 100644
--- a/integration/spring-security/src/main/java/org/keycloak/adapters/springsecurity/filter/KeycloakAuthenticationProcessingFilter.java
+++ b/integration/spring-security/src/main/java/org/keycloak/adapters/springsecurity/filter/KeycloakAuthenticationProcessingFilter.java
@@ -6,6 +6,7 @@ import org.keycloak.adapters.AuthOutcome;
 import org.keycloak.adapters.KeycloakDeployment;
 import org.keycloak.adapters.RequestAuthenticator;
 import org.keycloak.adapters.springsecurity.AdapterDeploymentContextBean;
+import org.keycloak.adapters.springsecurity.KeycloakAuthenticationException;
 import org.keycloak.adapters.springsecurity.authentication.KeycloakAuthenticationEntryPoint;
 import org.keycloak.adapters.springsecurity.authentication.SpringSecurityRequestAuthenticator;
 import org.keycloak.adapters.springsecurity.facade.SimpleHttpFacade;
@@ -22,6 +23,7 @@ import org.springframework.security.core.Authentication;
 import org.springframework.security.core.AuthenticationException;
 import org.springframework.security.core.context.SecurityContextHolder;
 import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
+import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler;
 import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
 import org.springframework.security.web.util.matcher.OrRequestMatcher;
 import org.springframework.security.web.util.matcher.RequestHeaderRequestMatcher;
@@ -41,7 +43,7 @@ import java.io.IOException;
  * @version $Revision: 1 $
  */
 public class KeycloakAuthenticationProcessingFilter extends AbstractAuthenticationProcessingFilter implements ApplicationContextAware {
-
+    public static final String DEFAULT_LOGIN_URL = "/sso/login";
     public static final String AUTHORIZATION_HEADER = "Authorization";
 
     /**
@@ -49,7 +51,7 @@ public class KeycloakAuthenticationProcessingFilter extends AbstractAuthenticati
      * and any request with a <code>Authorization</code> header.
      */
     public static final RequestMatcher DEFAULT_REQUEST_MATCHER =
-            new OrRequestMatcher(new AntPathRequestMatcher("/sso/login"), new RequestHeaderRequestMatcher("Authorization"));
+            new OrRequestMatcher(new AntPathRequestMatcher(DEFAULT_LOGIN_URL), new RequestHeaderRequestMatcher(AUTHORIZATION_HEADER));
 
     private static final Logger log = LoggerFactory.getLogger(KeycloakAuthenticationProcessingFilter.class);
 
@@ -67,6 +69,7 @@ public class KeycloakAuthenticationProcessingFilter extends AbstractAuthenticati
      */
     public KeycloakAuthenticationProcessingFilter(AuthenticationManager authenticationManager) {
         this(authenticationManager, DEFAULT_REQUEST_MATCHER);
+        setAuthenticationFailureHandler(new SimpleUrlAuthenticationFailureHandler(DEFAULT_LOGIN_URL));
     }
 
     /**
@@ -114,21 +117,23 @@ public class KeycloakAuthenticationProcessingFilter extends AbstractAuthenticati
                 = new SpringSecurityRequestAuthenticator(facade, request, deployment, tokenStore, -1);
 
         AuthOutcome result = authenticator.authenticate();
-        AuthChallenge challenge = authenticator.getChallenge();
-
         log.debug("Auth outcome: {}", result);
 
-        if (challenge != null) {
-            challenge.challenge(facade);
+        if (AuthOutcome.FAILED.equals(result)) {
+            throw new KeycloakAuthenticationException("Auth outcome: " + result);
         }
-
-        if (AuthOutcome.AUTHENTICATED.equals(result)) {
+        else if (AuthOutcome.AUTHENTICATED.equals(result)) {
             Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
             Assert.notNull(authentication, "Authentication SecurityContextHolder was null");
             return authenticationManager.authenticate(authentication);
         }
-
-        return null;
+        else {
+            AuthChallenge challenge = authenticator.getChallenge();
+            if (challenge != null) {
+                challenge.challenge(facade);
+            }
+            return null;
+        }
     }
 
     /**
diff --git a/integration/spring-security/src/main/java/org/keycloak/adapters/springsecurity/KeycloakAuthenticationException.java b/integration/spring-security/src/main/java/org/keycloak/adapters/springsecurity/KeycloakAuthenticationException.java
new file mode 100644
index 0000000..05e8436
--- /dev/null
+++ b/integration/spring-security/src/main/java/org/keycloak/adapters/springsecurity/KeycloakAuthenticationException.java
@@ -0,0 +1,13 @@
+package org.keycloak.adapters.springsecurity;
+
+import org.springframework.security.core.AuthenticationException;
+
+public class KeycloakAuthenticationException extends AuthenticationException {
+    public KeycloakAuthenticationException(String msg, Throwable t) {
+        super(msg, t);
+    }
+
+    public KeycloakAuthenticationException(String msg) {
+        super(msg);
+    }
+}
diff --git a/integration/spring-security/src/test/java/org/keycloak/adapters/springsecurity/filter/KeycloakAuthenticationProcessingFilterTest.java b/integration/spring-security/src/test/java/org/keycloak/adapters/springsecurity/filter/KeycloakAuthenticationProcessingFilterTest.java
index dfaa3e3..b135906 100644
--- a/integration/spring-security/src/test/java/org/keycloak/adapters/springsecurity/filter/KeycloakAuthenticationProcessingFilterTest.java
+++ b/integration/spring-security/src/test/java/org/keycloak/adapters/springsecurity/filter/KeycloakAuthenticationProcessingFilterTest.java
@@ -7,8 +7,12 @@ import org.keycloak.KeycloakSecurityContext;
 import org.keycloak.adapters.KeycloakAccount;
 import org.keycloak.adapters.KeycloakDeployment;
 import org.keycloak.adapters.springsecurity.AdapterDeploymentContextBean;
+import org.keycloak.adapters.springsecurity.KeycloakAuthenticationException;
 import org.keycloak.adapters.springsecurity.account.KeycloakRole;
 import org.keycloak.adapters.springsecurity.token.KeycloakAuthenticationToken;
+import org.keycloak.enums.SslRequired;
+import org.keycloak.representations.adapters.config.AdapterConfig;
+import org.keycloak.util.KeycloakUriBuilder;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 import org.springframework.context.ApplicationContext;
@@ -18,6 +22,7 @@ import org.springframework.security.authentication.BadCredentialsException;
 import org.springframework.security.core.Authentication;
 import org.springframework.security.core.AuthenticationException;
 import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.context.SecurityContextHolder;
 import org.springframework.security.web.authentication.AuthenticationFailureHandler;
 import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
 
@@ -106,6 +111,24 @@ public class KeycloakAuthenticationProcessingFilterTest {
     }
 
     @Test
+    public void testAttemptAuthenticationExpectRedirect() throws Exception {
+        when(keycloakDeployment.getAuthUrl()).thenReturn(KeycloakUriBuilder.fromUri("http://localhost:8080/auth"));
+        when(keycloakDeployment.getResourceName()).thenReturn("resource-name");
+        when(keycloakDeployment.getStateCookieName()).thenReturn("kc-cookie");
+        when(keycloakDeployment.getSslRequired()).thenReturn(SslRequired.NONE);
+        filter.attemptAuthentication(request, response);
+
+        verify(response).setStatus(302);
+        verify(response).setHeader(eq("Location"), startsWith("http://localhost:8080/auth"));
+    }
+
+    @Test(expected = KeycloakAuthenticationException.class)
+    public void testAttemptAuthenticationWithInvalidToken() throws Exception {
+        request.addHeader("Authorization", "Bearer xxx");
+        filter.attemptAuthentication(request, response);
+    }
+
+    @Test
     public void testSuccessfulAuthenticationInteractive() throws Exception {
         Authentication authentication = new KeycloakAuthenticationToken(keycloakAccount, authorities);
         filter.successfulAuthentication(request, response, chain, authentication);