mirror of
https://github.com/keycloak/keycloak.git
synced 2026-01-25 16:42:34 +00:00
Merge pull request #1233 from Smartling/KEYCLOAK-1274
Add Spring Security adapter documentation
This commit is contained in:
@@ -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;
|
||||
|
||||
275
docbook/reference/en/en-US/modules/spring-security-adapter.xml
Normal file
275
docbook/reference/en/en-US/modules/spring-security-adapter.xml
Normal file
@@ -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>
|
||||
Reference in New Issue
Block a user