From 566a58b5d82fd25b872a2381d07c383ae7e2738d Mon Sep 17 00:00:00 2001 From: Thomas Raehalme Date: Tue, 15 Dec 2015 11:53:10 +0200 Subject: [PATCH 1/3] Replaced AdapterDeploymentContextBean with AdapterDeploymentContextFactoryBean and added support for KeycloakConfigResolver. --- .../AdapterDeploymentContextBean.java | 64 --------------- .../AdapterDeploymentContextFactoryBean.java | 79 +++++++++++++++++++ .../authentication/KeycloakLogoutHandler.java | 15 ++-- .../KeycloakWebSecurityConfigurerAdapter.java | 23 ++++-- ...eycloakAuthenticationProcessingFilter.java | 11 +-- .../filter/KeycloakPreAuthActionsFilter.java | 5 +- .../AdapterDeploymentContextBeanTest.java | 56 ------------- ...apterDeploymentContextFactoryBeanTest.java | 77 ++++++++++++++++++ .../KeycloakLogoutHandlerTest.java | 9 ++- ...oakAuthenticationProcessingFilterTest.java | 9 ++- 10 files changed, 200 insertions(+), 148 deletions(-) delete mode 100644 integration/spring-security/src/main/java/org/keycloak/adapters/springsecurity/AdapterDeploymentContextBean.java create mode 100644 integration/spring-security/src/main/java/org/keycloak/adapters/springsecurity/AdapterDeploymentContextFactoryBean.java delete mode 100644 integration/spring-security/src/test/java/org/keycloak/adapters/springsecurity/AdapterDeploymentContextBeanTest.java create mode 100644 integration/spring-security/src/test/java/org/keycloak/adapters/springsecurity/AdapterDeploymentContextFactoryBeanTest.java diff --git a/integration/spring-security/src/main/java/org/keycloak/adapters/springsecurity/AdapterDeploymentContextBean.java b/integration/spring-security/src/main/java/org/keycloak/adapters/springsecurity/AdapterDeploymentContextBean.java deleted file mode 100644 index a517416396..0000000000 --- a/integration/spring-security/src/main/java/org/keycloak/adapters/springsecurity/AdapterDeploymentContextBean.java +++ /dev/null @@ -1,64 +0,0 @@ -package org.keycloak.adapters.springsecurity; - -import org.keycloak.adapters.AdapterDeploymentContext; -import org.keycloak.adapters.KeycloakDeployment; -import org.keycloak.adapters.KeycloakDeploymentBuilder; -import org.springframework.beans.factory.InitializingBean; -import org.springframework.core.io.Resource; - -import java.io.FileNotFoundException; -import java.io.IOException; - -/** - * Bean holding the {@link KeycloakDeployment} and {@link AdapterDeploymentContext} for this - * Spring application context. The Keycloak deployment is loaded from the required - * keycloak.json resource file. - * - * @author Scott Rossillo - * @version $Revision: 1 $ - */ -public class AdapterDeploymentContextBean implements InitializingBean { - - private final Resource keycloakConfigFileResource; - - private AdapterDeploymentContext deploymentContext; - private KeycloakDeployment deployment; - - public AdapterDeploymentContextBean(Resource keycloakConfigFileResource) { - this.keycloakConfigFileResource = keycloakConfigFileResource; - } - - @Override - public void afterPropertiesSet() throws Exception { - this.deployment = loadKeycloakDeployment(); - this.deploymentContext = new AdapterDeploymentContext(deployment); - } - - private KeycloakDeployment loadKeycloakDeployment() throws IOException { - - if (!keycloakConfigFileResource.isReadable()) { - throw new FileNotFoundException(String.format("Unable to locate Keycloak configuration file: %s", - keycloakConfigFileResource.getFilename())); - } - - return KeycloakDeploymentBuilder.build(keycloakConfigFileResource.getInputStream()); - } - - /** - * Returns the Keycloak {@link AdapterDeploymentContext} for this application context. - * - * @return the Keycloak {@link AdapterDeploymentContext} for this application context - */ - public AdapterDeploymentContext getDeploymentContext() { - return deploymentContext; - } - - /** - * Returns the {@link KeycloakDeployment} for this application context. - * - * @return the {@link KeycloakDeployment} for this application context - */ - public KeycloakDeployment getDeployment() { - return deployment; - } -} diff --git a/integration/spring-security/src/main/java/org/keycloak/adapters/springsecurity/AdapterDeploymentContextFactoryBean.java b/integration/spring-security/src/main/java/org/keycloak/adapters/springsecurity/AdapterDeploymentContextFactoryBean.java new file mode 100644 index 0000000000..d089ded86a --- /dev/null +++ b/integration/spring-security/src/main/java/org/keycloak/adapters/springsecurity/AdapterDeploymentContextFactoryBean.java @@ -0,0 +1,79 @@ +package org.keycloak.adapters.springsecurity; + +import java.io.FileNotFoundException; +import java.io.IOException; +import java.util.Objects; + +import org.keycloak.adapters.AdapterDeploymentContext; +import org.keycloak.adapters.KeycloakConfigResolver; +import org.keycloak.adapters.KeycloakDeployment; +import org.keycloak.adapters.KeycloakDeploymentBuilder; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import org.springframework.beans.factory.FactoryBean; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.core.io.Resource; + +/** + * {@link FactoryBean} that creates an {@link AdapterDeploymentContext} given a {@link Resource} defining the Keycloak + * client configuration or a {@link KeycloakConfigResolver} for multi-tenant environments. + * + * @author Thomas Raehalme + */ +public class AdapterDeploymentContextFactoryBean + implements FactoryBean, InitializingBean { + private static final Logger log = + LoggerFactory.getLogger(AdapterDeploymentContextFactoryBean.class); + private final Resource keycloakConfigFileResource; + private final KeycloakConfigResolver keycloakConfigResolver; + private AdapterDeploymentContext adapterDeploymentContext; + + public AdapterDeploymentContextFactoryBean(Resource keycloakConfigFileResource) { + this.keycloakConfigFileResource = Objects.requireNonNull(keycloakConfigFileResource); + this.keycloakConfigResolver = null; + } + + public AdapterDeploymentContextFactoryBean(KeycloakConfigResolver keycloakConfigResolver) { + this.keycloakConfigResolver = Objects.requireNonNull(keycloakConfigResolver); + this.keycloakConfigFileResource = null; + } + + @Override + public Class getObjectType() { + return AdapterDeploymentContext.class; + } + + @Override + public boolean isSingleton() { + return true; + } + + @Override + public void afterPropertiesSet() throws Exception { + if (keycloakConfigResolver != null) { + adapterDeploymentContext = new AdapterDeploymentContext(keycloakConfigResolver); + } + else { + log.info("Loading Keycloak deployment from configuration file: {}", keycloakConfigFileResource); + + KeycloakDeployment deployment = loadKeycloakDeployment(); + adapterDeploymentContext = new AdapterDeploymentContext(deployment); + } + } + + private KeycloakDeployment loadKeycloakDeployment() throws IOException { + if (!keycloakConfigFileResource.isReadable()) { + throw new FileNotFoundException(String.format("Unable to locate Keycloak configuration file: %s", + keycloakConfigFileResource.getFilename())); + } + + return KeycloakDeploymentBuilder.build(keycloakConfigFileResource.getInputStream()); + } + + @Override + public AdapterDeploymentContext getObject() throws Exception { + return adapterDeploymentContext; + } +} 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 27178ca2ad..c17dca1706 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 @@ -1,8 +1,10 @@ package org.keycloak.adapters.springsecurity.authentication; +import org.keycloak.adapters.AdapterDeploymentContext; import org.keycloak.adapters.KeycloakDeployment; import org.keycloak.adapters.RefreshableKeycloakSecurityContext; -import org.keycloak.adapters.springsecurity.AdapterDeploymentContextBean; +import org.keycloak.adapters.spi.HttpFacade; +import org.keycloak.adapters.springsecurity.facade.SimpleHttpFacade; import org.keycloak.adapters.springsecurity.token.KeycloakAuthenticationToken; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -23,11 +25,11 @@ public class KeycloakLogoutHandler implements LogoutHandler { private static final Logger log = LoggerFactory.getLogger(KeycloakLogoutHandler.class); - private AdapterDeploymentContextBean deploymentContextBean; + private AdapterDeploymentContext adapterDeploymentContext; - public KeycloakLogoutHandler(AdapterDeploymentContextBean deploymentContextBean) { - Assert.notNull(deploymentContextBean); - this.deploymentContextBean = deploymentContextBean; + public KeycloakLogoutHandler(AdapterDeploymentContext adapterDeploymentContext) { + Assert.notNull(adapterDeploymentContext); + this.adapterDeploymentContext = adapterDeploymentContext; } @Override @@ -45,7 +47,8 @@ public class KeycloakLogoutHandler implements LogoutHandler { } protected void handleSingleSignOut(HttpServletRequest request, HttpServletResponse response, KeycloakAuthenticationToken authenticationToken) { - KeycloakDeployment deployment = deploymentContextBean.getDeployment(); + HttpFacade facade = new SimpleHttpFacade(request, response); + KeycloakDeployment deployment = adapterDeploymentContext.resolveDeployment(facade); RefreshableKeycloakSecurityContext session = (RefreshableKeycloakSecurityContext) authenticationToken.getAccount().getKeycloakSecurityContext(); session.logout(deployment); } diff --git a/integration/spring-security/src/main/java/org/keycloak/adapters/springsecurity/config/KeycloakWebSecurityConfigurerAdapter.java b/integration/spring-security/src/main/java/org/keycloak/adapters/springsecurity/config/KeycloakWebSecurityConfigurerAdapter.java index b5ef6659e3..55c6b3c700 100644 --- a/integration/spring-security/src/main/java/org/keycloak/adapters/springsecurity/config/KeycloakWebSecurityConfigurerAdapter.java +++ b/integration/spring-security/src/main/java/org/keycloak/adapters/springsecurity/config/KeycloakWebSecurityConfigurerAdapter.java @@ -1,6 +1,8 @@ package org.keycloak.adapters.springsecurity.config; -import org.keycloak.adapters.springsecurity.AdapterDeploymentContextBean; +import org.keycloak.adapters.AdapterDeploymentContext; +import org.keycloak.adapters.KeycloakConfigResolver; +import org.keycloak.adapters.springsecurity.AdapterDeploymentContextFactoryBean; import org.keycloak.adapters.springsecurity.authentication.KeycloakAuthenticationEntryPoint; import org.keycloak.adapters.springsecurity.authentication.KeycloakAuthenticationProvider; import org.keycloak.adapters.springsecurity.authentication.KeycloakLogoutHandler; @@ -8,6 +10,7 @@ import org.keycloak.adapters.springsecurity.filter.KeycloakAuthenticationProcess import org.keycloak.adapters.springsecurity.filter.KeycloakCsrfRequestMatcher; import org.keycloak.adapters.springsecurity.filter.KeycloakPreAuthActionsFilter; import org.keycloak.adapters.springsecurity.management.HttpSessionManager; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.core.io.Resource; @@ -35,10 +38,20 @@ public abstract class KeycloakWebSecurityConfigurerAdapter extends WebSecurityCo @Value("${keycloak.configurationFile:WEB-INF/keycloak.json}") private Resource keycloakConfigFileResource; + @Autowired(required = false) + private KeycloakConfigResolver keycloakConfigResolver; @Bean - protected AdapterDeploymentContextBean adapterDeploymentContextBean() { - return new AdapterDeploymentContextBean(keycloakConfigFileResource); + protected AdapterDeploymentContext adapterDeploymentContext() throws Exception { + AdapterDeploymentContextFactoryBean factoryBean; + if (keycloakConfigResolver != null) { + factoryBean = new AdapterDeploymentContextFactoryBean(keycloakConfigResolver); + } + else { + factoryBean = new AdapterDeploymentContextFactoryBean(keycloakConfigFileResource); + } + factoryBean.afterPropertiesSet(); + return factoryBean.getObject(); } protected AuthenticationEntryPoint authenticationEntryPoint() { @@ -70,8 +83,8 @@ public abstract class KeycloakWebSecurityConfigurerAdapter extends WebSecurityCo return new HttpSessionManager(); } - protected KeycloakLogoutHandler keycloakLogoutHandler() { - return new KeycloakLogoutHandler(adapterDeploymentContextBean()); + protected KeycloakLogoutHandler keycloakLogoutHandler() throws Exception { + return new KeycloakLogoutHandler(adapterDeploymentContext()); } protected abstract SessionAuthenticationStrategy sessionAuthenticationStrategy(); 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 965c1624ab..04c6ed3367 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 @@ -1,11 +1,12 @@ package org.keycloak.adapters.springsecurity.filter; +import org.keycloak.adapters.AdapterDeploymentContext; import org.keycloak.adapters.AdapterTokenStore; import org.keycloak.adapters.spi.AuthChallenge; import org.keycloak.adapters.spi.AuthOutcome; import org.keycloak.adapters.KeycloakDeployment; import org.keycloak.adapters.RequestAuthenticator; -import org.keycloak.adapters.springsecurity.AdapterDeploymentContextBean; +import org.keycloak.adapters.spi.HttpFacade; import org.keycloak.adapters.springsecurity.KeycloakAuthenticationException; import org.keycloak.adapters.springsecurity.authentication.KeycloakAuthenticationEntryPoint; import org.keycloak.adapters.springsecurity.authentication.SpringSecurityRequestAuthenticator; @@ -56,7 +57,7 @@ public class KeycloakAuthenticationProcessingFilter extends AbstractAuthenticati private static final Logger log = LoggerFactory.getLogger(KeycloakAuthenticationProcessingFilter.class); private ApplicationContext applicationContext; - private AdapterDeploymentContextBean adapterDeploymentContextBean; + private AdapterDeploymentContext adapterDeploymentContext; private AdapterTokenStoreFactory adapterTokenStoreFactory = new SpringSecurityAdapterTokenStoreFactory(); private AuthenticationManager authenticationManager; @@ -100,7 +101,7 @@ public class KeycloakAuthenticationProcessingFilter extends AbstractAuthenticati @Override public void afterPropertiesSet() { - adapterDeploymentContextBean = applicationContext.getBean(AdapterDeploymentContextBean.class); + adapterDeploymentContext = applicationContext.getBean(AdapterDeploymentContext.class); super.afterPropertiesSet(); } @@ -110,8 +111,8 @@ public class KeycloakAuthenticationProcessingFilter extends AbstractAuthenticati log.debug("Attempting Keycloak authentication"); - KeycloakDeployment deployment = adapterDeploymentContextBean.getDeployment(); - SimpleHttpFacade facade = new SimpleHttpFacade(request, response); + HttpFacade facade = new SimpleHttpFacade(request, response); + KeycloakDeployment deployment = adapterDeploymentContext.resolveDeployment(facade); AdapterTokenStore tokenStore = adapterTokenStoreFactory.createAdapterTokenStore(deployment, request); RequestAuthenticator authenticator = new SpringSecurityRequestAuthenticator(facade, request, deployment, tokenStore, -1); diff --git a/integration/spring-security/src/main/java/org/keycloak/adapters/springsecurity/filter/KeycloakPreAuthActionsFilter.java b/integration/spring-security/src/main/java/org/keycloak/adapters/springsecurity/filter/KeycloakPreAuthActionsFilter.java index 2363b3f1f3..565ae624ba 100755 --- a/integration/spring-security/src/main/java/org/keycloak/adapters/springsecurity/filter/KeycloakPreAuthActionsFilter.java +++ b/integration/spring-security/src/main/java/org/keycloak/adapters/springsecurity/filter/KeycloakPreAuthActionsFilter.java @@ -5,7 +5,6 @@ import org.keycloak.adapters.spi.HttpFacade; import org.keycloak.adapters.NodesRegistrationManagement; import org.keycloak.adapters.PreAuthActionsHandler; import org.keycloak.adapters.spi.UserSessionManagement; -import org.keycloak.adapters.springsecurity.AdapterDeploymentContextBean; import org.keycloak.adapters.springsecurity.facade.SimpleHttpFacade; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -47,9 +46,7 @@ public class KeycloakPreAuthActionsFilter extends GenericFilterBean implements A @Override protected void initFilterBean() throws ServletException { - AdapterDeploymentContextBean contextBean = applicationContext.getBean(AdapterDeploymentContextBean.class); - deploymentContext = contextBean.getDeploymentContext(); - management.tryRegister(contextBean.getDeployment()); + deploymentContext = applicationContext.getBean(AdapterDeploymentContext.class); } @Override diff --git a/integration/spring-security/src/test/java/org/keycloak/adapters/springsecurity/AdapterDeploymentContextBeanTest.java b/integration/spring-security/src/test/java/org/keycloak/adapters/springsecurity/AdapterDeploymentContextBeanTest.java deleted file mode 100644 index 3510db7f7a..0000000000 --- a/integration/spring-security/src/test/java/org/keycloak/adapters/springsecurity/AdapterDeploymentContextBeanTest.java +++ /dev/null @@ -1,56 +0,0 @@ -package org.keycloak.adapters.springsecurity; - - -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; -import org.springframework.core.io.ClassPathResource; -import org.springframework.core.io.Resource; - -import java.io.FileNotFoundException; - -import static org.junit.Assert.assertNotNull; - -public class AdapterDeploymentContextBeanTest { - - @Rule - public ExpectedException expectedException = ExpectedException.none(); - - private AdapterDeploymentContextBean adapterDeploymentContextBean; - - @Test - public void should_create_deployment_and_deployment_context() throws Exception { - - //given: - adapterDeploymentContextBean = new AdapterDeploymentContextBean(getCorrectResource()); - - //when: - adapterDeploymentContextBean.afterPropertiesSet(); - - //then - assertNotNull(adapterDeploymentContextBean.getDeployment()); - assertNotNull(adapterDeploymentContextBean.getDeploymentContext()); - } - - private Resource getCorrectResource() { - return new ClassPathResource("keycloak.json"); - } - - @Test - public void should_throw_exception_when_configuration_file_was_not_found() throws Exception { - - //given: - adapterDeploymentContextBean = new AdapterDeploymentContextBean(getEmptyResource()); - - //then: - expectedException.expect(FileNotFoundException.class); - expectedException.expectMessage("Unable to locate Keycloak configuration file: no-file.json"); - - //when: - adapterDeploymentContextBean.afterPropertiesSet(); - } - - private Resource getEmptyResource() { - return new ClassPathResource("no-file.json"); - } -} diff --git a/integration/spring-security/src/test/java/org/keycloak/adapters/springsecurity/AdapterDeploymentContextFactoryBeanTest.java b/integration/spring-security/src/test/java/org/keycloak/adapters/springsecurity/AdapterDeploymentContextFactoryBeanTest.java new file mode 100644 index 0000000000..6a3b39fd37 --- /dev/null +++ b/integration/spring-security/src/test/java/org/keycloak/adapters/springsecurity/AdapterDeploymentContextFactoryBeanTest.java @@ -0,0 +1,77 @@ +package org.keycloak.adapters.springsecurity; + +import java.io.FileNotFoundException; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; + +import org.keycloak.adapters.KeycloakConfigResolver; +import org.keycloak.adapters.KeycloakDeployment; +import org.keycloak.adapters.spi.HttpFacade; + +import org.springframework.core.io.ClassPathResource; +import org.springframework.core.io.Resource; + +import static org.junit.Assert.assertNotNull; + +public class AdapterDeploymentContextFactoryBeanTest { + @Rule + public ExpectedException expectedException = ExpectedException.none(); + + private AdapterDeploymentContextFactoryBean adapterDeploymentContextFactoryBean; + + @Test + public void should_create_adapter_deployment_context_from_configuration_file() throws Exception { + // given: + adapterDeploymentContextFactoryBean = new AdapterDeploymentContextFactoryBean(getCorrectResource()); + + // when: + adapterDeploymentContextFactoryBean.afterPropertiesSet(); + + // then + assertNotNull(adapterDeploymentContextFactoryBean.getObject()); + } + + private Resource getCorrectResource() { + return new ClassPathResource("keycloak.json"); + } + + @Test + public void should_throw_exception_when_configuration_file_was_not_found() throws Exception { + // given: + adapterDeploymentContextFactoryBean = new AdapterDeploymentContextFactoryBean(getEmptyResource()); + + // then: + expectedException.expect(FileNotFoundException.class); + expectedException.expectMessage("Unable to locate Keycloak configuration file: no-file.json"); + + // when: + adapterDeploymentContextFactoryBean.afterPropertiesSet(); + } + + private Resource getEmptyResource() { + return new ClassPathResource("no-file.json"); + } + + @Test + public void should_create_adapter_deployment_context_from_keycloak_config_resolver() throws Exception { + // given: + adapterDeploymentContextFactoryBean = new AdapterDeploymentContextFactoryBean(getKeycloakConfigResolver()); + + // when: + adapterDeploymentContextFactoryBean.afterPropertiesSet(); + + // then: + assertNotNull(adapterDeploymentContextFactoryBean.getObject()); + } + + private KeycloakConfigResolver getKeycloakConfigResolver() { + return new KeycloakConfigResolver() { + @Override + public KeycloakDeployment resolve(HttpFacade.Request facade) { + return null; + } + }; + } +} 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 index cc751c4b76..2f44107ba6 100755 --- 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 @@ -2,10 +2,11 @@ package org.keycloak.adapters.springsecurity.authentication; import org.junit.Before; import org.junit.Test; +import org.keycloak.adapters.AdapterDeploymentContext; import org.keycloak.adapters.KeycloakDeployment; import org.keycloak.adapters.OidcKeycloakAccount; import org.keycloak.adapters.RefreshableKeycloakSecurityContext; -import org.keycloak.adapters.springsecurity.AdapterDeploymentContextBean; +import org.keycloak.adapters.spi.HttpFacade; import org.keycloak.adapters.springsecurity.account.KeycloakRole; import org.keycloak.adapters.springsecurity.token.KeycloakAuthenticationToken; import org.mockito.Mock; @@ -35,7 +36,7 @@ public class KeycloakLogoutHandlerTest { private MockHttpServletResponse response; @Mock - private AdapterDeploymentContextBean adapterDeploymentContextBean; + private AdapterDeploymentContext adapterDeploymentContext; @Mock private OidcKeycloakAccount keycloakAccount; @@ -52,11 +53,11 @@ public class KeycloakLogoutHandlerTest { public void setUp() throws Exception { MockitoAnnotations.initMocks(this); keycloakAuthenticationToken = mock(KeycloakAuthenticationToken.class); - keycloakLogoutHandler = new KeycloakLogoutHandler(adapterDeploymentContextBean); + keycloakLogoutHandler = new KeycloakLogoutHandler(adapterDeploymentContext); request = new MockHttpServletRequest(); response = new MockHttpServletResponse(); - when(adapterDeploymentContextBean.getDeployment()).thenReturn(keycloakDeployment); + when(adapterDeploymentContext.resolveDeployment(any(HttpFacade.class))).thenReturn(keycloakDeployment); when(keycloakAuthenticationToken.getAccount()).thenReturn(keycloakAccount); when(keycloakAccount.getKeycloakSecurityContext()).thenReturn(session); } 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 ab4c03258f..1ccc3671b5 100755 --- 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 @@ -4,9 +4,10 @@ import org.junit.Before; import org.junit.Test; import org.keycloak.KeycloakPrincipal; import org.keycloak.KeycloakSecurityContext; +import org.keycloak.adapters.AdapterDeploymentContext; import org.keycloak.adapters.KeycloakDeployment; import org.keycloak.adapters.OidcKeycloakAccount; -import org.keycloak.adapters.springsecurity.AdapterDeploymentContextBean; +import org.keycloak.adapters.spi.HttpFacade; import org.keycloak.adapters.springsecurity.KeycloakAuthenticationException; import org.keycloak.adapters.springsecurity.account.KeycloakRole; import org.keycloak.adapters.springsecurity.token.KeycloakAuthenticationToken; @@ -45,7 +46,7 @@ public class KeycloakAuthenticationProcessingFilterTest { private AuthenticationManager authenticationManager; @Mock - private AdapterDeploymentContextBean adapterDeploymentContextBean; + private AdapterDeploymentContext adapterDeploymentContext; @Mock private FilterChain chain; @@ -85,8 +86,8 @@ public class KeycloakAuthenticationProcessingFilterTest { filter.setAuthenticationSuccessHandler(successHandler); filter.setAuthenticationFailureHandler(failureHandler); - when(applicationContext.getBean(eq(AdapterDeploymentContextBean.class))).thenReturn(adapterDeploymentContextBean); - when(adapterDeploymentContextBean.getDeployment()).thenReturn(keycloakDeployment); + when(applicationContext.getBean(eq(AdapterDeploymentContext.class))).thenReturn(adapterDeploymentContext); + when(adapterDeploymentContext.resolveDeployment(any(HttpFacade.class))).thenReturn(keycloakDeployment); when(keycloakAccount.getPrincipal()).thenReturn( new KeycloakPrincipal(UUID.randomUUID().toString(), keycloakSecurityContext)); From 57971ce0b2670b13c189212edf52c3ed842044eb Mon Sep 17 00:00:00 2001 From: Thomas Raehalme Date: Mon, 4 Jan 2016 21:09:36 +0200 Subject: [PATCH 2/3] Changed docs to match the new code. --- .../en/en-US/modules/spring-security-adapter.xml | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/docbook/auth-server-docs/reference/en/en-US/modules/spring-security-adapter.xml b/docbook/auth-server-docs/reference/en/en-US/modules/spring-security-adapter.xml index 33c2aa287d..0d3c20c0df 100644 --- a/docbook/auth-server-docs/reference/en/en-US/modules/spring-security-adapter.xml +++ b/docbook/auth-server-docs/reference/en/en-US/modules/spring-security-adapter.xml @@ -115,7 +115,10 @@ public class SecurityConfig extends KeycloakWebSecurityConfigurerAdapter - + + + + @@ -124,7 +127,7 @@ public class SecurityConfig extends KeycloakWebSecurityConfigurerAdapter - + @@ -157,6 +160,15 @@ public class SecurityConfig extends KeycloakWebSecurityConfigurerAdapter +
+ Multi Tenancy + + The Keycloak Spring Security adapter also supports multi tenancy. Instead of injecting + AdapterDeploymentContextFactoryBean with the path to keycloak.json you + can inject an implementation of the KeycloakConfigResolver interface. More details on how + to implement the KeycloakConfigResolver can be found in . + +
Naming Security Roles From 8356409b44258656e588f146948661d74e7b6828 Mon Sep 17 00:00:00 2001 From: Thomas Raehalme Date: Mon, 4 Jan 2016 21:16:37 +0200 Subject: [PATCH 3/3] Fixed some typos in the docs and added paragraph regarding GrantedAuthoritiesMapper. --- .../en/en-US/modules/spring-security-adapter.xml | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/docbook/auth-server-docs/reference/en/en-US/modules/spring-security-adapter.xml b/docbook/auth-server-docs/reference/en/en-US/modules/spring-security-adapter.xml index 0d3c20c0df..dce3d3d899 100644 --- a/docbook/auth-server-docs/reference/en/en-US/modules/spring-security-adapter.xml +++ b/docbook/auth-server-docs/reference/en/en-US/modules/spring-security-adapter.xml @@ -1,7 +1,7 @@
Spring Security Adapter - To to secure an application with Spring Security and Keyloak, add this adapter as a dependency to your project. + To secure an application with Spring Security and Keycloak, add this adapter as a dependency to your project. You then have to provide some extra beans in your Spring Security configuration file and add the Keycloak security filter to your pipeline. @@ -176,6 +176,14 @@ public class SecurityConfig extends KeycloakWebSecurityConfigurerAdapter For example, an administrator role must be declared in Keycloak as ROLE_ADMIN or similar, not simply ADMIN. + + The class org.keycloak.adapters.springsecurity.authentication.KeycloakAuthenticationProvider + supports an optional org.springframework.security.core.authority.mapping.GrantedAuthoritiesMapper + which can be used to map roles coming from Keycloak to roles recognized by Spring Security. Use, for example, + org.springframework.security.core.authority.mapping.SimpleAuthorityMapper to insert the + ROLE_ prefix and convert the role name to upper case. The class is part of Spring Security + Core module. +
Client to Client Support