Search code examples
springspring-securitysaml-2.0spring-security-oauth2spring-saml

Getting error from spring-security.xml in case of multi-tenacy with Oauth,SAML, and spring-security


I need to provide multi-tenacy support for my web-application. I have added support for OAUTH2 with spring-security successfully. My application was running properly and accessible using normal login (username and password) and also with OAuth token.

But now I have to provide SSO support for one of our customer so I added Spring-SAML for SP and ADFS for IDP. From now problems started I am able to use either saml based url or rest based URL but not able to provide both at a time.

Below lines are from my spring-security.xml file

<security:http pattern="/oauth/token" create-session="stateless"
        authentication-manager-ref="clientAuthenticationManager">
        <security:intercept-url pattern="/oauth/token" access="IS_AUTHENTICATED_FULLY" />
        <security:anonymous enabled="false" />
        <security:http-basic entry-point-ref="clientAuthenticationEntryPoint" />
        <security:custom-filter ref="clientCredentialsTokenEndpointFilter"
            after="BASIC_AUTH_FILTER" />
        <security:access-denied-handler ref="oauthAccessDeniedHandler" />
    </security:http>

    <!-- SAML starts -->

   <security:http entry-point-ref="samlEntryPoint" >
        <security:intercept-url pattern="/oauth/**" access="ROLE_USER" />
        <security:intercept-url pattern="/saml" access="IS_AUTHENTICATED_FULLY"/> 
        <security:custom-filter before="FIRST" ref="metadataGeneratorFilter"/>
        <security:custom-filter after="BASIC_AUTH_FILTER" ref="samlFilter"/>
    </security:http>

     <!-- SAML ends -->

    <security:http pattern="/rest/**"  access-decision-manager-ref="accessDecisionManager">
        <security:anonymous enabled="false" />
        <security:form-login login-page="/login.html" authentication-success-handler-ref="mercatusSavedRequestHandler"
            authentication-failure-url="/login.jsp?login_error=true"/> 

        <security:intercept-url pattern="/rest/**" access="ROLE_USER" />
        <security:custom-filter ref="resourceServerFilter" before="PRE_AUTH_FILTER" />
        <security:custom-filter ref="mercatusAjaxTimeoutFilter" after="EXCEPTION_TRANSLATION_FILTER"/>
        <security:access-denied-handler ref="oauthAccessDeniedHandler"/>
    </security:http>

    <security:http access-denied-page="/login.jsp?login_error=true">
        <security:intercept-url pattern="/index.html" access="ROLE_USER" />
        <security:intercept-url pattern="/saml/**" access="ROLE_USER" />
        <security:intercept-url pattern="/oauth/**" access="ROLE_USER" />    
        <security:intercept-url pattern="/customer/*" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
        <security:intercept-url pattern="/**" access="IS_AUTHENTICATED_ANONYMOUSLY" />  
        <security:form-login login-page="/login.html" authentication-success-handler-ref="mercatusSavedRequestHandler"
            authentication-failure-url="/login.jsp?login_error=true"/> 
        <security:logout delete-cookies="true" invalidate-session="true" logout-success-url="/login.html"/>
        <security:anonymous />
    </security:http>

And saml related secuirty tags are given below

<bean id="samlFilter" class="org.springframework.security.web.FilterChainProxy">
    <security:filter-chain-map request-matcher="ant">
        <security:filter-chain pattern="/saml/login/**" filters="samlEntryPoint"/>
        <security:filter-chain pattern="/saml/logout/**" filters="samlLogoutFilter"/>
        <security:filter-chain pattern="/saml/metadata/**" filters="metadataDisplayFilter"/>
        <security:filter-chain pattern="/saml/SSO/**" filters="samlWebSSOProcessingFilter"/>
        <security:filter-chain pattern="/saml/SSOHoK/**" filters="samlWebSSOHoKProcessingFilter"/>
        <security:filter-chain pattern="/saml/SingleLogout/**" filters="samlLogoutProcessingFilter"/>
        <security:filter-chain pattern="/saml/discovery/**" filters="samlIDPDiscovery"/>
    </security:filter-chain-map>
</bean>

<bean id="samlEntryPoint" class="org.springframework.security.saml.SAMLEntryPoint">
    <property name="defaultProfileOptions">
        <bean class="org.springframework.security.saml.websso.WebSSOProfileOptions">
            <property name="includeScoping" value="false"/>
        </bean>
    </property>
</bean>

when I try to start tomcat getting below error.

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.security.filterChainProxy': Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: A universal match pattern ('/**') is defined  before other patterns in the filter chain, causing them to be ignored. Please check the ordering in your <security:http> namespace or FilterChainProxy bean configuration
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1455)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:519)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:294)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:225)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:291)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:609)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:918)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:469)
    at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:383)
    at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:283)
    at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:111)
    at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4887)
    at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5381)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
    at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1559)
    at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1549)
    at java.util.concurrent.FutureTask.run(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    at java.lang.Thread.run(Unknown Source)
Caused by: java.lang.IllegalArgumentException: A universal match pattern ('/**') is defined  before other patterns in the filter chain, causing them to be ignored. Please check the ordering in your <security:http> namespace or FilterChainProxy bean configuration
    at org.springframework.security.config.http.DefaultFilterChainValidator.checkPathOrder(DefaultFilterChainValidator.java:49)
    at org.springframework.security.config.http.DefaultFilterChainValidator.validate(DefaultFilterChainValidator.java:39)
    at org.springframework.security.web.FilterChainProxy.afterPropertiesSet(FilterChainProxy.java:151)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1514)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1452)
    ... 21 more

Any help will be appreciated. Thanks in advance.


Solution

  • Your "SAML starts" filter chain doesn't define a pattern, so it defaults to "/**" and then you define another chain with pattern="/rest/**". You probably need to use a pattern matcher in the SAML one, or else move it to the end because it is the default.