This project targets a smooth integration between spring-security-saml and Spring Boot by exposing a set of configurer adapters while dealing with the nitty-gritty and boiler plate of spring-security-saml configuration internally.
-
Add the following maven dependency to your project:
<dependency> <groupId>com.github.ulisesbocchio</groupId> <artifactId>spring-boot-security-saml</artifactId> <version>1.6</version> </dependency>
-
Add the
@EnableSAMLSSOannotation to your Spring Boot Application on any@Configurationclass:@SpringBootApplication @EnableSAMLSSO public class ServiceProviderApplication { ... }
-
Start configuring your SAML 2.0 Service provider (see below).
For those familiar with spring-security-saml this plugin exposes most of it configuration points through 2 different forms that are fully interchangeable and combine-able except when providing custom implementations and instances.
The two configuration flavors are:
Configuring your Service Provider through the JAVA DSL is pretty straight forward, and it follows the configurer/adapter/builder style that Spring Security currently has. A specific Interface and Adapter class are provided for the configuration, these are: ServiceProviderConfigurer and ServiceProviderConfigurerAdapter respectively.
In most scenarios, you should be good with simply extending ServiceProviderConfigurerAdapter and overriding the #configure(ServiceProviderBuilder serviceProvider) method. This is an example:
@Configuration
public static class MyServiceProviderConfig extends ServiceProviderConfigurerAdapter {
@Override
public void configure(ServiceProviderBuilder serviceProvider) throws Exception {
// @formatter:off
serviceProvider
.metadataGenerator() //(1)
.entityId("localhost-demo")
.and()
.sso() //(2)
.defaultSuccessURL("/home")
.idpSelectionPageURL("/idpselection")
.and()
.logout() //(3)
.defaultTargetURL("/")
.and()
.metadataManager() //(4)
.metadataLocations("classpath:/idp-ssocircle.xml")
.refreshCheckInterval(0)
.and()
.extendedMetadata() //(5)
.idpDiscoveryEnabled(true)
.and()
.keyManager() //(6)
.privateKeyDERLocation("classpath:/localhost.key.der")
.publicKeyPEMLocation("classpath:/localhost.cert");
// @formatter:on
}
}It is not strictly necessary for this class to be a @Configuration class, it could also be a Spring Bean. As far as it is exposed in the Application Context, the plugin will pick it up and configure the Service Provider accordingly.
The other two methods in the Configurer/Adapter, #configure(HttpSecurity http) and #configure(WebSecurity web) allow for in-place customization of Spring Security's HttpSecurity and WebSecurity objects, without requiring extending other configurers/adapters to be implemented/extended, basically a shortcut.
In the above example, you can see how the following items are specified:
- The Service Provider entity ID
- The default success URL (redirect after successful login through the IDP if not saved request present) and a custom IDP Selection page URL for selecting and Identity Provider before login.
- The default logout URL, basically the URL to be redirected after successful logout.
- The IDP metadata to be used to send requests to the IDP and validate incoming calls from the IDP, and metadata reflesh interval (0 means never).
- Enable IDP discovery, so when SAML SSO kicks in, we'll be presented with an IDP selection page before the actual login, (set to false to use default IDP).
- And we provide a custom private key (DER format) and public cert (PEM format) to be used for signing outgoing requests. (To be configured in the IDP side also).
This configuration is equivalent to the one showcased in the Configuration Properties section.
For more documentation and available options, please see the JavaDoc of ServiceProviderBuilder and read the Configuration Cookbook.
To accomplish the same configuration as above you can also use the regular Spring Security WebSecurityConfigurerAdapter to configure SAML authentication for your application in conjunction with any other security configuration your application may need.
For this, besides creating your regular WebSecurityConfigurerAdapter configuration, you'll also need a bean of type SAMLConfigurerBean that you'll be able to plug into your WebSecurityConfigurerAdapter. The following is an example that showcases the
exact same configuration from the previous section:
@Configuration
public static class MyServiceProviderConfig extends WebSecurityConfigurerAdapter {
@Bean
SAMLConfigurerBean saml() {
return new SAMLConfigurerBean();
}
@Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Override
public void configure(HttpSecurity http) throws Exception {
// @formatter:off
http.httpBasic()
.disable()
.csrf()
.disable()
.anonymous()
.and()
.apply(saml())
.serviceProvider()
.metadataGenerator() //(1)
.entityId("localhost-demo")
.and()
.sso() //(2)
.defaultSuccessURL("/home")
.idpSelectionPageURL("/idpselection")
.and()
.logout() //(3)
.defaultTargetURL("/")
.and()
.metadataManager() //(4)
.metadataLocations("classpath:/idp-ssocircle.xml")
.refreshCheckInterval(0)
.and()
.extendedMetadata() //(5)
.idpDiscoveryEnabled(true)
.and()
.keyManager() //(6)
.privateKeyDERLocation("classpath:/localhost.key.der")
.publicKeyPEMLocation("classpath:/localhost.cert")
.http()
.authorizeRequests()
.requestMatchers(saml().endpointsMatcher())
.permitAll()
.and()
.authorizeRequests()
.anyRequest()
.authenticated();
// @formatter:on
}
}This is basically a manual configuration of Spring Security on which the SAMLConfigurerBean bean is defined and used as argument to HttpSecurity.apply() which registers the configurer and returns ServiceProviderBuilder for further customization.
The ServiceProviderBuilder returned is the same type used in the previous example on the ServiceProviderConfigurerAdapter.configure method.
After the ServiceProviderBuilder is used, an http() method exists to go back the the HttpSecurity configuration. In the example, the lines:
http() // or just http
.authorizeRequests()
.requestMatchers(saml().endpointsMatcher())
.permitAll()Are required to expose the SAML Service Provider endpoints without any security.
Configuring your Service Provider through configuration properties is pretty straight forward and most configurations could be accomplished this way. The two limitations that exists are: You can only configure what is exposed as properties, obviously, and you cannot provide specific implementations or instances of the different Spring Security SAML classes/interfaces. If you need to provide custom implementations of certain types or a more dynamic configuration you'll need to use the Java DSL approach for that configuration, but as expressed before, you can configure as much as you can through properties, while using the DSL configuration for any dynamic or custom implementations configuration. You can mix the two flavors.
For a full list of all configuration properties available see this document. Not included here to avoid clutter.
The following properties snippet is a sample configuration through application.yml.
saml:
sso:
default-success-url: /home #(1)
idp-selection-page-url: /idpSelection #(2)
metadata-generator:
entity-id: localhost-demo #(3)
logout:
default-target-url: / #(4)
idps:
metadata-location: classpath:/idp-ssocircle.xml #(5)
metadata-manager:
refresh-check-interval: 0 #(6)
extended-metadata:
idp-discovery-enabled: true #(7)
key-manager:
private-key-der-location: classpath:/localhost.key.der #(8)
public-key-pem-location: classpath:/localhost.cert #(9)In the above example, you can see how the following items are specified:
- The default success URL (redirect after successful login through the IDP if not saved request present) and
- A custom IDP Selection page URL for selecting and Identity Provider before login.
- The Service Provider entity ID
- The default logout URL, basically the URL to be redirected after successful logout.
- The IDP metadata to be used to send requests to the IDP and validate incoming calls from the IDP,
- And metadata reflesh interval (0 means never).
- Enable IDP discovery, so when SAML SSO kicks in, we'll be presented with an IDP selection page before the actual login, (set to false to use default IDP).
- Provide a custom private key (DER format)
- And public cert (PEM format) to be used for signing outgoing requests. (To be configured in the IDP side also).
All you need on the Java side is the @EnableSAMLSSO annotation for the default configuration, although if you wanna define a ServiceProviderConfigurerAdapter that's fine too, and you can select which configuration you keep on the DSL side and what you leave on the properties, it's up to you.
If what you need is to use a standard WebSecurityConfigurerAdapter to configure SAML and you would like to use properties also, you can do that too.
Using the above properties all you need to do is to apply the SAMLConfigurerBean to the HttpSecurity and disable security for the SAML endpoints:
@Configuration
public static class MyServiceProviderConfig extends WebSecurityConfigurerAdapter {
@Bean
SAMLConfigurerBean saml() {
return new SAMLConfigurerBean();
}
@Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Override
public void configure(HttpSecurity http) throws Exception {
// @formatter:off
http.httpBasic()
.disable()
.csrf()
.disable()
.anonymous()
.and()
.apply(saml())
.http()
.authorizeRequests()
.requestMatchers(saml().endpointsMatcher())
.permitAll()
.and()
.authorizeRequests()
.anyRequest()
.authenticated();
// @formatter:on
}
}For a more thorough description of the properties please see JavaDoc of class SAMLSSOProperties and ServiceProviderBuilder. For configuration examples, see Configuration Cookbook.
No default templates are provided with spring-boot-security-saml for IDP selection page, home page, or default logout page. Developers need to configure the desired template engine and make sure that the URLs configured for this plugin are resolvable through Spring MVC.
For instance, the following configuration is used in the Demo apps to specify the index page that is also mapped to the logout page:
@Configuration
public static class MvcConfig extends WebMvcConfigurerAdapter {
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("index");
}
}In the other hand, idpSelection.html and home.html under resources/templates/ in the Demo apps are implicitly defined as view controllers by Spring Boot's Thymeleaf auto-configuration.
For more information on how to configure Spring MVC please visit Spring MVC's Documentation page and Spring Boot's Web Applications Documentation.
In spring-boot-security-saml-demo-dsl, spring-boot-security-saml-demo-props there are working demos of this plugin using the Java DSL style and Configuration Properties style respectively. Also, checkout spring-boot-security-saml-demo-okta for a working demo using Okta as IDP.
In spring-security-saml-sample there's a fully working Spring Boot app integrated with regular Spring Security SAML and several IdPs (SSOCircle, Ping Identity, OKTA, OneLogin). In this sample you can check the amount of configuration required to integrate spring-security-saml with Spring Boot.
These examples are intended to cover some usual Spring Security SAML configuration scenarios through this plugin to showcase the dynamics of the new configuration style. It is not meant as extensive documentation of Spring Security SAML or the SAML 2.0 standard. For documentation regarding Spring Security SAML and SAML 2.0 please see Further Documentation section.
*** Coming Soon ***
For configuration specifics about Spring Security SAML please visit their Documentation Reference. For SAML 2.0 documentation these are good starting points: