diff --git a/docbook/reference/en/en-US/master.xml b/docbook/reference/en/en-US/master.xml
index 31dcd82..218a1aa 100755
--- a/docbook/reference/en/en-US/master.xml
+++ b/docbook/reference/en/en-US/master.xml
@@ -17,6 +17,7 @@
<!ENTITY Jetty8Adapter SYSTEM "modules/jetty8-adapter.xml">
<!ENTITY FuseAdapter SYSTEM "modules/fuse-adapter.xml">
<!ENTITY SpringBootAdapter SYSTEM "modules/spring-boot-adapter.xml">
+ <!ENTITY SpringSecurityAdapter SYSTEM "modules/spring-security-adapter.xml">
<!ENTITY InstalledApplications SYSTEM "modules/installed-applications.xml">
<!ENTITY Logout SYSTEM "modules/logout.xml">
<!ENTITY SAML SYSTEM "modules/saml.xml">
@@ -97,6 +98,7 @@ This one is short
&FuseAdapter;
&JavascriptAdapter;
&SpringBootAdapter;
+ &SpringSecurityAdapter;
&InstalledApplications;
&Logout;
&MultiTenancy;
diff --git a/docbook/reference/en/en-US/modules/spring-security-adapter.xml b/docbook/reference/en/en-US/modules/spring-security-adapter.xml
new file mode 100644
index 0000000..33c2aa2
--- /dev/null
+++ b/docbook/reference/en/en-US/modules/spring-security-adapter.xml
@@ -0,0 +1,275 @@
+<section id="spring-security-adapter">
+ <title>Spring Security Adapter</title>
+ <para>
+ To to secure an application with Spring Security and Keyloak, 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.
+ </para>
+ <para>
+ Unlike the other Keycloak Adapters, you should not configure your security in web.xml. However, keycloak.json is still required.
+ </para>
+ <section>
+ <title>Adapter Installation</title>
+ <para>
+ Add Keycloak Spring Security adapter as a dependency to your Maven POM or Gradle build.
+ </para>
+ <para>
+ <programlisting>
+ <![CDATA[
+<dependency>
+ <groupId>org.keycloak</groupId>
+ <artifactId>keycloak-spring-security-adapter</artifactId>
+ <version>&project.version;</version>
+</dependency>
+]]>
+ </programlisting>
+ </para>
+ </section>
+ <section>
+ <title>Spring Security Configuration</title>
+ <para>
+ The Keycloak Spring Security adapter takes advantage of Spring Security's flexible security configuration syntax.
+ </para>
+ <section>
+ <title>Java Configuration</title>
+ <para>
+ Keycloak provides a KeycloakWebSecurityConfigurerAdapter as a convenient base class for creating a
+ <ulink url="http://docs.spring.io/spring-security/site/docs/4.0.x/apidocs/org/springframework/security/config/annotation/web/WebSecurityConfigurer.html">WebSecurityConfigurer</ulink>
+ instance. The implementation allows customization by overriding methods. While its use is not required, it greatly simplifies your security context configuration.
+ </para>
+ <para>
+ <programlisting>
+ <![CDATA[
+@Configuration
+@EnableWebSecurity
+@ComponentScan(basePackageClasses = KeycloakSecurityComponents.class)
+public class SecurityConfig extends KeycloakWebSecurityConfigurerAdapter
+{
+ /**
+ * Registers the KeycloakAuthenticationProvider with the authentication manager.
+ */
+ @Autowired
+ public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
+ auth.authenticationProvider(keycloakAuthenticationProvider());
+ }
+
+ /**
+ * Defines the session authentication strategy.
+ */
+ @Bean
+ @Override
+ protected SessionAuthenticationStrategy sessionAuthenticationStrategy() {
+ return new RegisterSessionAuthenticationStrategy(new SessionRegistryImpl());
+ }
+
+ @Override
+ protected void configure(HttpSecurity http) throws Exception
+ {
+ super.configure(http);
+ http
+ .authorizeRequests()
+ .antMatchers("/customers*").hasRole("USER")
+ .antMatchers("/admin*").hasRole("ADMIN")
+ .anyRequest().permitAll();
+ }
+}
+]]>
+ </programlisting>
+ </para>
+ <para>
+ You must provide a session authentication strategy bean which should be of type
+ <code>RegisterSessionAuthenticationStrategy</code> for public or confidential applications and
+ <code>NullAuthenticatedSessionStrategy</code> for bearer-only applications.
+ </para>
+ <para>
+ Spring Security's <code>SessionFixationProtectionStrategy</code> is currently not supported because it changes
+ the session identifier after login via Keycloak. If the session identifier changes, universal log out will not
+ work because Keycloak is unaware of the new session identifier.
+ </para>
+ </section>
+ <section>
+ <title>XML Configuration</title>
+ <para>
+ While Spring Security's XML namespace simplifies configuration, customizing the configuration can be a bit
+ verbose.
+ </para>
+ <para>
+ <programlisting>
+ <![CDATA[
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:context="http://www.springframework.org/schema/context"
+ xmlns:security="http://www.springframework.org/schema/security"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="
+ http://www.springframework.org/schema/beans
+ http://www.springframework.org/schema/beans/spring-beans.xsd
+ http://www.springframework.org/schema/context
+ http://www.springframework.org/schema/context/spring-context.xsd
+ http://www.springframework.org/schema/security
+ http://www.springframework.org/schema/security/spring-security.xsd">
+
+ <context:component-scan base-package="org.keycloak.adapters.springsecurity" />
+
+ <security:authentication-manager alias="authenticationManager">
+ <security:authentication-provider ref="keycloakAuthenticationProvider" />
+ </security:authentication-manager>
+
+ <bean id="adapterDeploymentContextBean" class="org.keycloak.adapters.springsecurity.AdapterDeploymentContextBean" />
+ <bean id="keycloakAuthenticationEntryPoint" class="org.keycloak.adapters.springsecurity.authentication.KeycloakAuthenticationEntryPoint" />
+ <bean id="keycloakAuthenticationProvider" class="org.keycloak.adapters.springsecurity.authentication.KeycloakAuthenticationProvider" />
+ <bean id="keycloakPreAuthActionsFilter" class="org.keycloak.adapters.springsecurity.filter.KeycloakPreAuthActionsFilter" />
+ <bean id="keycloakAuthenticationProcessingFilter" class="org.keycloak.adapters.springsecurity.filter.KeycloakAuthenticationProcessingFilter">
+ <constructor-arg name="authenticationManager" ref="authenticationManager" />
+ </bean>
+
+ <bean id="keycloakLogoutHandler" class="org.keycloak.adapters.springsecurity.authentication.KeycloakLogoutHandler">
+ <constructor-arg ref="adapterDeploymentContextBean" />
+ </bean>
+
+ <bean id="logoutFilter" class="org.springframework.security.web.authentication.logout.LogoutFilter">
+ <constructor-arg name="logoutSuccessUrl" value="/" />
+ <constructor-arg name="handlers">
+ <list>
+ <ref bean="keycloakLogoutHandler" />
+ <bean class="org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler" />
+ </list>
+ </constructor-arg>
+ <property name="logoutRequestMatcher">
+ <bean class="org.springframework.security.web.util.matcher.AntPathRequestMatcher">
+ <constructor-arg name="pattern" value="/sso/logout**" />
+ <constructor-arg name="httpMethod" value="GET" />
+ </bean>
+ </property>
+ </bean>
+
+ <security:http auto-config="false" entry-point-ref="keycloakAuthenticationEntryPoint">
+ <security:custom-filter ref="keycloakPreAuthActionsFilter" before="LOGOUT_FILTER" />
+ <security:custom-filter ref="keycloakAuthenticationProcessingFilter" before="FORM_LOGIN_FILTER" />
+ <security:intercept-url pattern="/customers**" access="ROLE_USER" />
+ <security:intercept-url pattern="/admin**" access="ROLE_ADMIN" />
+ <security:custom-filter ref="logoutFilter" position="LOGOUT_FILTER" />
+ </security:http>
+
+</beans>
+]]>
+ </programlisting>
+ </para>
+ </section>
+ </section>
+ <section>
+ <title>Naming Security Roles</title>
+ <para>
+ Spring Security, when using role-based authentication, requires that role names start with <code>ROLE_</code>.
+ For example, an administrator role must be declared in Keycloak as <code>ROLE_ADMIN</code> or similar, not simply
+ <code>ADMIN</code>.
+ </para>
+ </section>
+ <section>
+ <title>Client to Client Support</title>
+ <para>
+ To simplify communication between clients, Keycloak provides an extension of Spring's <code>RestTemplate</code> that
+ handles bearer token authentication for you. To enable this feature your security configuration must add the
+ <code>KeycloakRestTemplate</code> bean. Note that it must be scoped as a prototype to function correctly.
+ </para>
+ <para>
+ For Java configuration:
+ <programlisting>
+ <![CDATA[
+@Configuration
+@EnableWebSecurity
+@ComponentScan(basePackageClasses = KeycloakSecurityComponents.class)
+public class SecurityConfig extends KeycloakWebSecurityConfigurerAdapter {
+
+ ...
+
+ @Autowired
+ public KeycloakClientRequestFactory keycloakClientRequestFactory;
+
+ @Bean
+ @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
+ public KeycloakRestTemplate keycloakRestTemplate() {
+ return new KeycloakRestTemplate(keycloakClientRequestFactory);
+ }
+
+ ...
+}
+]]>
+ </programlisting>
+ </para>
+ <para>
+ For XML configuration:
+ <programlisting>
+ <![CDATA[
+<bean id="keycloakRestTemplate" class="org.keycloak.adapters.springsecurity.client.KeycloakRestTemplate" scope="prototype">
+ <constructor-arg name="factory" ref="keycloakClientRequestFactory" />
+</bean>
+]]>
+ </programlisting>
+ </para>
+ <para>
+ Your application code can then use <code>KeycloakRestTemplate</code> any time it needs to make a call to another
+ client. For example:
+ <programlisting>
+ <![CDATA[
+
+@Service
+public class RemoteProductService implements ProductService {
+
+ @Autowired
+ private KeycloakRestTemplate template;
+
+ private String endpoint;
+
+ @Override
+ public List<String> getProducts() {
+ ResponseEntity<String[]> response = template.getForEntity(endpoint, String[].class);
+ return Arrays.asList(response.getBody());
+ }
+}
+
+]]>
+ </programlisting>
+ </para>
+ </section>
+ <section>
+ <title>Spring Boot Configuration</title>
+ <para>
+ Spring Boot attempts to eagerly register filter beans with the web application context. Therefore,
+ when running the Keycloak Spring Security adapter in a Spring Boot environment, it may be necessary to add two
+ <code>FilterRegistrationBean</code>s to your security configuration to prevent the Keycloak filters from being
+ registered
+ twice.
+ </para>
+ <para>
+ <programlisting>
+ <![CDATA[
+@Configuration
+@EnableWebSecurity
+public class SecurityConfig extends KeycloakWebSecurityConfigurerAdapter
+{
+ ...
+
+ @Bean
+ public FilterRegistrationBean keycloakAuthenticationProcessingFilterRegistrationBean(
+ KeycloakAuthenticationProcessingFilter filter) {
+ FilterRegistrationBean registrationBean = new FilterRegistrationBean(filter);
+ registrationBean.setEnabled(false);
+ return registrationBean;
+ }
+
+ @Bean
+ public FilterRegistrationBean keycloakPreAuthActionsFilterRegistrationBean(
+ KeycloakPreAuthActionsFilter filter) {
+ FilterRegistrationBean registrationBean = new FilterRegistrationBean(filter);
+ registrationBean.setEnabled(false);
+ return registrationBean;
+ }
+
+ ...
+}
+]]>
+ </programlisting>
+ </para>
+ </section>
+</section>