keycloak-aplcache
Changes
integration/spring-security/src/main/java/org/keycloak/adapters/springsecurity/filter/KeycloakAuthenticationProcessingFilter.java 25(+15 -10)
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);