com.netflix.genie.web.security.saml.SAMLConfig.java Source code

Java tutorial

Introduction

Here is the source code for com.netflix.genie.web.security.saml.SAMLConfig.java

Source

/*
 *
 *  Copyright 2016 Netflix, Inc.
 *
 *     Licensed under the Apache License, Version 2.0 (the "License");
 *     you may not use this file except in compliance with the License.
 *     You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 *     Unless required by applicable law or agreed to in writing, software
 *     distributed under the License is distributed on an "AS IS" BASIS,
 *     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *     See the License for the specific language governing permissions and
 *     limitations under the License.
 *
 */
package com.netflix.genie.web.security.saml;

import com.google.common.collect.Lists;
import com.netflix.genie.web.security.x509.X509UserDetailsService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager;
import org.apache.velocity.app.VelocityEngine;
import org.opensaml.saml2.metadata.provider.HTTPMetadataProvider;
import org.opensaml.saml2.metadata.provider.MetadataProviderException;
import org.opensaml.xml.parse.ParserPool;
import org.opensaml.xml.parse.StaticBasicParserPool;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.saml.SAMLAuthenticationProvider;
import org.springframework.security.saml.SAMLBootstrap;
import org.springframework.security.saml.SAMLDiscovery;
import org.springframework.security.saml.SAMLEntryPoint;
import org.springframework.security.saml.SAMLLogoutFilter;
import org.springframework.security.saml.SAMLLogoutProcessingFilter;
import org.springframework.security.saml.SAMLProcessingFilter;
import org.springframework.security.saml.SAMLWebSSOHoKProcessingFilter;
import org.springframework.security.saml.context.SAMLContextProviderImpl;
import org.springframework.security.saml.context.SAMLContextProviderLB;
import org.springframework.security.saml.key.JKSKeyManager;
import org.springframework.security.saml.key.KeyManager;
import org.springframework.security.saml.log.SAMLDefaultLogger;
import org.springframework.security.saml.metadata.CachingMetadataManager;
import org.springframework.security.saml.metadata.ExtendedMetadata;
import org.springframework.security.saml.metadata.ExtendedMetadataDelegate;
import org.springframework.security.saml.metadata.MetadataDisplayFilter;
import org.springframework.security.saml.metadata.MetadataGenerator;
import org.springframework.security.saml.metadata.MetadataGeneratorFilter;
import org.springframework.security.saml.parser.ParserPoolHolder;
import org.springframework.security.saml.processor.HTTPArtifactBinding;
import org.springframework.security.saml.processor.HTTPPAOS11Binding;
import org.springframework.security.saml.processor.HTTPPostBinding;
import org.springframework.security.saml.processor.HTTPRedirectDeflateBinding;
import org.springframework.security.saml.processor.HTTPSOAP11Binding;
import org.springframework.security.saml.processor.SAMLBinding;
import org.springframework.security.saml.processor.SAMLProcessorImpl;
import org.springframework.security.saml.userdetails.SAMLUserDetailsService;
import org.springframework.security.saml.util.VelocityFactory;
import org.springframework.security.saml.websso.ArtifactResolutionProfile;
import org.springframework.security.saml.websso.ArtifactResolutionProfileImpl;
import org.springframework.security.saml.websso.SingleLogoutProfile;
import org.springframework.security.saml.websso.SingleLogoutProfileImpl;
import org.springframework.security.saml.websso.WebSSOProfile;
import org.springframework.security.saml.websso.WebSSOProfileConsumer;
import org.springframework.security.saml.websso.WebSSOProfileConsumerHoKImpl;
import org.springframework.security.saml.websso.WebSSOProfileConsumerImpl;
import org.springframework.security.saml.websso.WebSSOProfileECPImpl;
import org.springframework.security.saml.websso.WebSSOProfileImpl;
import org.springframework.security.saml.websso.WebSSOProfileOptions;
import org.springframework.security.web.DefaultSecurityFilterChain;
import org.springframework.security.web.FilterChainProxy;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.access.channel.ChannelProcessingFilter;
import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;
import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler;
import org.springframework.security.web.authentication.logout.LogoutHandler;
import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;
import org.springframework.security.web.authentication.logout.SimpleUrlLogoutSuccessHandler;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Timer;

/**
 * Security configuration for SAML based authentication.
 * <p>
 * Modified from: https://github.com/vdenotaris/spring-boot-security-saml-sample which is basically a port of the
 * context-xml from Spring SAML example.
 *
 * @author tgianos
 * @since 3.0.0
 */
@ConditionalOnProperty("genie.security.saml.enabled")
@Configuration
@Order(5)
//@EnableGlobalMethodSecurity(securedEnabled = true)
@Slf4j
public class SAMLConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private ResourceLoader resourceLoader;

    @Autowired
    private X509UserDetailsService x509UserDetailsService;

    @Autowired
    private SAMLProperties samlProperties;

    /**
     * Initialization of OpenSAML library.
     *
     * @return the OpenSAML bootstrap object
     * @see SAMLBootstrap
     */
    @Bean
    public static SAMLBootstrap samlBootstrap() {
        return new SAMLBootstrap();
    }

    /**
     * Initialize the velocity engine.
     *
     * @return The velocity engine.
     * @see VelocityEngine
     */
    @Bean
    public VelocityEngine velocityEngine() {
        return VelocityFactory.getEngine();
    }

    /**
     * Parser pool used for the OpenSAML parsing.
     *
     * @return The parser pool
     * @see StaticBasicParserPool
     */
    @Bean(initMethod = "initialize")
    public StaticBasicParserPool parserPool() {
        return new StaticBasicParserPool();
    }

    /**
     * The holder for the parser poole.
     *
     * @return The parser pool holder
     * @see ParserPoolHolder
     */
    @Bean(name = "parserPoolHolder")
    public ParserPoolHolder parserPoolHolder() {
        return new ParserPoolHolder();
    }

    /**
     * Connection pool for the HTTP Client.
     *
     * @return a Multithreaded connection manager
     * @see MultiThreadedHttpConnectionManager
     */
    @Bean
    public MultiThreadedHttpConnectionManager multiThreadedHttpConnectionManager() {
        return new MultiThreadedHttpConnectionManager();
    }

    /**
     * The HTTP Client used to communicate with the IDP.
     *
     * @return The http client
     * @see HttpClient
     */
    @Bean
    public HttpClient httpClient() {
        return new HttpClient(multiThreadedHttpConnectionManager());
    }

    /**
     * Parses the response SAML messages.
     *
     * @param samlUserDetailsService The user details service to use
     * @return The SAML authentication provider
     * @see SAMLAuthenticationProvider
     */
    @Bean
    public SAMLAuthenticationProvider samlAuthenticationProvider(
            final SAMLUserDetailsService samlUserDetailsService) {
        final SAMLAuthenticationProvider samlAuthenticationProvider = new SAMLAuthenticationProvider();
        samlAuthenticationProvider.setUserDetails(samlUserDetailsService);
        samlAuthenticationProvider.setForcePrincipalAsString(false);
        return samlAuthenticationProvider;
    }

    /**
     * Provider of the SAML context.
     *
     * @param properties The SAML properties to use
     * @return the context provider implementation
     * @see SAMLContextProviderImpl
     */
    @Bean
    public SAMLContextProviderImpl contextProvider(final SAMLProperties properties) {
        if (properties.getLoadBalancer() != null) {
            log.info(
                    "Using SAMLContextProviderLB implementation of SAMLContextProvider for context provider bean.");
            final SAMLContextProviderLB lb = new SAMLContextProviderLB();
            final SAMLProperties.LoadBalancer lbProps = properties.getLoadBalancer();
            final String scheme = lbProps.getScheme();
            log.info("Setting the load balancer scheme to {}", scheme);
            lb.setScheme(scheme);
            final String serverName = lbProps.getServerName();
            log.info("Setting the load balancer server name to {}", serverName);
            lb.setServerName(serverName);
            final String contextPath = lbProps.getContextPath();
            log.info("Setting the load balancer context path to {}", contextPath);
            lb.setContextPath(contextPath);
            final int serverPort = lbProps.getServerPort();
            log.info("Setting the load balancer port to {}", serverPort);
            lb.setServerPort(serverPort);
            final boolean includeServerPort = lbProps.isIncludeServerPortInRequestURL();
            log.info("Setting whether to include the server port in the request URL to {}", includeServerPort);
            lb.setIncludeServerPortInRequestURL(includeServerPort);
            return lb;
        } else {
            log.info(
                    "Using SAMLContextProviderImpl implementation of SAMLContextProvider for context provider bean.");
            return new SAMLContextProviderImpl();
        }
    }

    /**
     * The Logger used by the SAML package.
     *
     * @return the logger
     * @see SAMLDefaultLogger
     */
    @Bean
    public SAMLDefaultLogger samlLogger() {
        return new SAMLDefaultLogger();
    }

    /**
     * SAML 2.0 WebSSO Assertion Consumer.
     *
     * @return The consumer
     * @see WebSSOProfileConsumer
     * @see WebSSOProfileConsumerImpl
     */
    @Bean
    public WebSSOProfileConsumer webSSOprofileConsumer() {
        return new WebSSOProfileConsumerImpl();
    }

    /**
     * SAML 2.0 Holder-of-Key WebSSO Assertion Consumer.
     *
     * @return The holder of key consumer implementation
     * @see WebSSOProfileConsumerHoKImpl
     */
    @Bean
    public WebSSOProfileConsumerHoKImpl hokWebSSOprofileConsumer() {
        return new WebSSOProfileConsumerHoKImpl();
    }

    /**
     * SAML 2.0 Web SSO profile.
     *
     * @return The web profile
     * @see WebSSOProfile
     * @see WebSSOProfileImpl
     */
    @Bean
    public WebSSOProfile webSSOprofile() {
        return new WebSSOProfileImpl();
    }

    /**
     * SAML 2.0 Holder-of-Key Web SSO profile.
     *
     * @return the HoK profile
     * @see WebSSOProfileConsumerHoKImpl
     */
    @Bean
    public WebSSOProfileConsumerHoKImpl hokWebSSOProfile() {
        return new WebSSOProfileConsumerHoKImpl();
    }

    /**
     * SAML 2.0 ECP profile.
     *
     * @return The ECP profile
     * @see WebSSOProfileECPImpl
     */
    @Bean
    public WebSSOProfileECPImpl ecpprofile() {
        return new WebSSOProfileECPImpl();
    }

    /**
     * The logout profile for SAML single logout.
     *
     * @return The logout profile
     * @see SingleLogoutProfile
     * @see SingleLogoutProfileImpl
     */
    @Bean
    public SingleLogoutProfile logoutProfile() {
        return new SingleLogoutProfileImpl();
    }

    /**
     * Central storage of cryptographic keys.
     *
     * @return The key manager used for everything
     * @see KeyManager
     */
    @Bean
    public KeyManager keyManager() {
        final Resource storeFile = this.resourceLoader
                .getResource("classpath:" + this.samlProperties.getKeystore().getName());
        final Map<String, String> passwords = new HashMap<>();
        passwords.put(this.samlProperties.getKeystore().getDefaultKey().getName(),
                this.samlProperties.getKeystore().getDefaultKey().getPassword());
        return new JKSKeyManager(storeFile, this.samlProperties.getKeystore().getPassword(), passwords,
                this.samlProperties.getKeystore().getDefaultKey().getName());
    }

    /**
     * The Web SSO profile options.
     *
     * @return The profile options for web sso
     * @see WebSSOProfileOptions
     */
    @Bean
    public WebSSOProfileOptions defaultWebSSOProfileOptions() {
        final WebSSOProfileOptions webSSOProfileOptions = new WebSSOProfileOptions();
        webSSOProfileOptions.setIncludeScoping(false);
        return webSSOProfileOptions;
    }

    /**
     * Entry point to initialize authentication, default values taken from properties file.
     *
     * @return The SAML entry point
     * @see SAMLEntryPoint
     */
    @Bean
    public SAMLEntryPoint samlEntryPoint() {
        final SAMLEntryPoint samlEntryPoint = new SAMLEntryPoint();
        samlEntryPoint.setDefaultProfileOptions(defaultWebSSOProfileOptions());
        return samlEntryPoint;
    }

    /**
     * Setup the extended metadata for the SAML request.
     *
     * @return The extended metadata
     * @see ExtendedMetadata
     */
    @Bean
    public ExtendedMetadata extendedMetadata() {
        return new ExtendedMetadata();
    }

    /**
     * Setup the IDP discovery service.
     *
     * @return The discovery service
     * @see SAMLDiscovery
     */
    @Bean
    public SAMLDiscovery samlIDPDiscovery() {
        return new SAMLDiscovery();
    }

    /**
     * Setup the extended metadata delegate for the IDP.
     *
     * @param properties The SAML properties
     * @return The sso circle of trust metadata provider configured via the url.
     * @throws MetadataProviderException On any configuration error
     * @see ExtendedMetadataDelegate
     * @see HTTPMetadataProvider
     */
    @Bean
    @Qualifier("idp-ssocircle")
    public ExtendedMetadataDelegate ssoCircleExtendedMetadataProvider(final SAMLProperties properties)
            throws MetadataProviderException {
        // Create a daemon timer for updating the IDP metadata from the server
        final Timer backgroundTaskTimer = new Timer(true);
        final HTTPMetadataProvider httpMetadataProvider = new HTTPMetadataProvider(backgroundTaskTimer,
                httpClient(), properties.getIdp().getServiceProviderMetadataURL());
        httpMetadataProvider.setParserPool(parserPool());
        final ExtendedMetadataDelegate extendedMetadataDelegate = new ExtendedMetadataDelegate(httpMetadataProvider,
                extendedMetadata());
        extendedMetadataDelegate.setMetadataTrustCheck(true);
        extendedMetadataDelegate.setMetadataRequireSignature(false);
        return extendedMetadataDelegate;
    }

    /**
     * Get the metadata manager for the IDP metadata. This version caches locally and refreshes periodically.
     *
     * @param ssoCircleExtendedMetadataProvider The extended metadata delegate
     * @return The metadata manager
     * @throws MetadataProviderException on any configuration error
     * @see CachingMetadataManager
     */
    @Bean
    @Qualifier("metadata")
    public CachingMetadataManager metadata(final ExtendedMetadataDelegate ssoCircleExtendedMetadataProvider)
            throws MetadataProviderException {
        return new CachingMetadataManager(Lists.newArrayList(ssoCircleExtendedMetadataProvider));
    }

    /**
     * Generates default SP metadata if none is set.
     *
     * @return The metadata generator filter
     * @see MetadataGenerator
     */
    @Bean
    public MetadataGenerator metadataGenerator() {
        final MetadataGenerator metadataGenerator = new MetadataGenerator();
        metadataGenerator.setEntityId(this.samlProperties.getSp().getEntityId());
        metadataGenerator.setExtendedMetadata(extendedMetadata());
        metadataGenerator.setIncludeDiscoveryExtension(false);
        metadataGenerator.setKeyManager(keyManager());
        if (this.samlProperties.getSp().getEntityBaseURL() != null) {
            metadataGenerator.setEntityBaseURL(this.samlProperties.getSp().getEntityBaseURL());
        }
        return metadataGenerator;
    }

    /**
     * The filter is waiting for connections on URL suffixed with filterSuffix and presents SP metadata there.
     *
     * @return the filter that will display the SP information
     * @see MetadataDisplayFilter
     */
    @Bean
    public MetadataDisplayFilter metadataDisplayFilter() {
        return new MetadataDisplayFilter();
    }

    /**
     * Handler deciding where to redirect user after successful login.
     *
     * @return The login success handler
     * @see SavedRequestAwareAuthenticationSuccessHandler
     */
    @Bean
    public SavedRequestAwareAuthenticationSuccessHandler successRedirectHandler() {
        return new SavedRequestAwareAuthenticationSuccessHandler();
    }

    /**
     * Handler deciding where to redirect user after failed login.
     *
     * @return Authentication failure handler
     * @see SimpleUrlAuthenticationFailureHandler
     */
    @Bean
    public SimpleUrlAuthenticationFailureHandler authenticationFailureHandler() {
        final SimpleUrlAuthenticationFailureHandler failureHandler = new SimpleUrlAuthenticationFailureHandler();
        failureHandler.setUseForward(true);
        failureHandler.setDefaultFailureUrl("/error");
        return failureHandler;
    }

    /**
     * Filter to process holder of key sso requests.
     *
     * @return The filter
     * @throws Exception For any configuration error
     * @see SAMLWebSSOHoKProcessingFilter
     */
    @Bean
    public SAMLWebSSOHoKProcessingFilter samlWebSSOHoKProcessingFilter() throws Exception {
        final SAMLWebSSOHoKProcessingFilter samlWebSSOHoKProcessingFilter = new SAMLWebSSOHoKProcessingFilter();
        samlWebSSOHoKProcessingFilter.setAuthenticationSuccessHandler(successRedirectHandler());
        samlWebSSOHoKProcessingFilter.setAuthenticationManager(authenticationManager());
        samlWebSSOHoKProcessingFilter.setAuthenticationFailureHandler(authenticationFailureHandler());
        return samlWebSSOHoKProcessingFilter;
    }

    /**
     * Processing filter for WebSSO profile messages.
     *
     * @return The SAML processing filter
     * @throws Exception on any configuration error
     * @see SAMLProcessingFilter
     */
    @Bean
    public SAMLProcessingFilter samlWebSSOProcessingFilter() throws Exception {
        final SAMLProcessingFilter samlWebSSOProcessingFilter = new SAMLProcessingFilter();
        samlWebSSOProcessingFilter.setAuthenticationManager(authenticationManager());
        samlWebSSOProcessingFilter.setAuthenticationSuccessHandler(successRedirectHandler());
        samlWebSSOProcessingFilter.setAuthenticationFailureHandler(authenticationFailureHandler());
        return samlWebSSOProcessingFilter;
    }

    /**
     * The metadata generator filter which generates metadata for the SP if non is pre-configured.
     *
     * @return The metadata generator filter
     */
    @Bean
    public MetadataGeneratorFilter metadataGeneratorFilter() {
        return new MetadataGeneratorFilter(metadataGenerator());
    }

    /**
     * Handler for successful logout.
     *
     * @return the logout location to redirect the user to after they logout
     * @see SimpleUrlLogoutSuccessHandler
     */
    @Bean
    public SimpleUrlLogoutSuccessHandler successLogoutHandler() {
        final SimpleUrlLogoutSuccessHandler successLogoutHandler = new SimpleUrlLogoutSuccessHandler();
        //TODO: Change this location as it looks like could send into a circular loop
        successLogoutHandler.setDefaultTargetUrl("/");
        return successLogoutHandler;
    }

    /**
     * Logout handler terminating local session.
     *
     * @return The security context logout handler
     * @see SecurityContextLogoutHandler
     */
    @Bean
    public SecurityContextLogoutHandler logoutHandler() {
        final SecurityContextLogoutHandler logoutHandler = new SecurityContextLogoutHandler();
        logoutHandler.setInvalidateHttpSession(true);
        logoutHandler.setClearAuthentication(true);
        return logoutHandler;
    }

    /**
     * Filter to handle logout requests.
     *
     * @return The filter
     * @see SAMLLogoutProcessingFilter
     */
    @Bean
    public SAMLLogoutProcessingFilter samlLogoutProcessingFilter() {
        return new SAMLLogoutProcessingFilter(successLogoutHandler(), logoutHandler());
    }

    /**
     * Overrides default logout processing filter with the one processing SAML messages.
     *
     * @return The logout filter
     * @see SAMLLogoutFilter
     */
    @Bean
    public SAMLLogoutFilter samlLogoutFilter() {
        return new SAMLLogoutFilter(successLogoutHandler(), new LogoutHandler[] { logoutHandler() },
                new LogoutHandler[] { logoutHandler() });
    }

    // Bindings
    private ArtifactResolutionProfile artifactResolutionProfile() {
        final ArtifactResolutionProfileImpl artifactResolutionProfile = new ArtifactResolutionProfileImpl(
                httpClient());
        artifactResolutionProfile.setProcessor(new SAMLProcessorImpl(soapBinding()));
        return artifactResolutionProfile;
    }

    /**
     * HTTP Artifact binding.
     *
     * @param parserPool     The parser pool to use
     * @param velocityEngine The velocity engine to use
     * @return The artifact binding
     * @see HTTPArtifactBinding
     */
    @Bean
    public HTTPArtifactBinding artifactBinding(final ParserPool parserPool, final VelocityEngine velocityEngine) {
        return new HTTPArtifactBinding(parserPool, velocityEngine, artifactResolutionProfile());
    }

    /**
     * A SOAP binding to use.
     *
     * @return a SOAP binding
     * @see HTTPSOAP11Binding
     */
    @Bean
    public HTTPSOAP11Binding soapBinding() {
        return new HTTPSOAP11Binding(parserPool());
    }

    /**
     * A HTTP POST binding to use.
     *
     * @return The post binding
     * @see HTTPPostBinding
     */
    @Bean
    public HTTPPostBinding httpPostBinding() {
        return new HTTPPostBinding(parserPool(), velocityEngine());
    }

    /**
     * A HTTP redirect binding to use.
     *
     * @return The redirect binding
     * @see HTTPRedirectDeflateBinding
     */
    @Bean
    public HTTPRedirectDeflateBinding httpRedirectDeflateBinding() {
        return new HTTPRedirectDeflateBinding(parserPool());
    }

    /**
     * A SOAP binding to use.
     *
     * @return a SOAP binding
     * @see HTTPSOAP11Binding
     */
    @Bean
    public HTTPSOAP11Binding httpSOAP11Binding() {
        return new HTTPSOAP11Binding(parserPool());
    }

    /**
     * A PAOS binding to use.
     *
     * @return The PAOS binding
     * @see HTTPPAOS11Binding
     */
    @Bean
    public HTTPPAOS11Binding httpPAOS11Binding() {
        return new HTTPPAOS11Binding(parserPool());
    }

    /**
     * The SAML processor that includes bindings for various communication protocols with the IDP.
     *
     * @return The saml processor
     * @see SAMLProcessorImpl
     */
    @Bean
    public SAMLProcessorImpl processor() {
        final List<SAMLBinding> bindings = Lists.newArrayList(httpRedirectDeflateBinding(), httpPostBinding(),
                artifactBinding(parserPool(), velocityEngine()), httpSOAP11Binding(), httpPAOS11Binding());
        return new SAMLProcessorImpl(bindings);
    }

    /**
     * Define the security filter chain in order to support SSO Auth by using SAML 2.0.
     *
     * @return Filter chain proxy
     * @throws Exception on any configuration problem
     * @see FilterChainProxy
     */
    @Bean
    public FilterChainProxy samlFilter() throws Exception {
        final List<SecurityFilterChain> chains = new ArrayList<>();
        chains.add(new DefaultSecurityFilterChain(new AntPathRequestMatcher("/saml/login/**"), samlEntryPoint()));
        chains.add(
                new DefaultSecurityFilterChain(new AntPathRequestMatcher("/saml/logout/**"), samlLogoutFilter()));
        chains.add(new DefaultSecurityFilterChain(new AntPathRequestMatcher("/saml/metadata/**"),
                metadataDisplayFilter()));
        chains.add(new DefaultSecurityFilterChain(new AntPathRequestMatcher("/saml/SSO/**"),
                samlWebSSOProcessingFilter()));
        chains.add(new DefaultSecurityFilterChain(new AntPathRequestMatcher("/saml/SSOHoK/**"),
                samlWebSSOHoKProcessingFilter()));
        chains.add(new DefaultSecurityFilterChain(new AntPathRequestMatcher("/saml/SingleLogout/**"),
                samlLogoutProcessingFilter()));
        chains.add(new DefaultSecurityFilterChain(new AntPathRequestMatcher("/saml/discovery/**"),
                samlIDPDiscovery()));
        return new FilterChainProxy(chains);
    }

    /**
     * Defines the web based security configuration.
     *
     * @param http It allows configuring web based security for specific http requests.
     * @throws Exception on any error
     */
    @Override
    protected void configure(final HttpSecurity http) throws Exception {
        // @formatter:off
        http.httpBasic().authenticationEntryPoint(samlEntryPoint());
        http.csrf().disable();
        http.addFilterBefore(metadataGeneratorFilter(), ChannelProcessingFilter.class).addFilterAfter(samlFilter(),
                BasicAuthenticationFilter.class);
        http.antMatcher("/**").authorizeRequests().antMatchers("/actuator/**").permitAll().antMatchers("/api/**")
                .permitAll().antMatchers("/error").permitAll().antMatchers("/saml/**").permitAll().anyRequest()
                .authenticated().and().x509().authenticationUserDetailsService(this.x509UserDetailsService);
        http.logout().logoutSuccessUrl("/");
        // @formatter:on
    }

    protected void setSamlProperties(final SAMLProperties samlProperties) {
        this.samlProperties = samlProperties;
    }

    protected void setResourceLoader(final ResourceLoader resourceLoader) {
        this.resourceLoader = resourceLoader;
    }
}