When deploying an application that uses SAML2 for authentication on Tomcat 7, I encountered an issue related to the creation of beans in the Spring Security configuration. The problem manifests as an ambiguity in constructor arguments when Spring attempts to instantiate certain beans defined in the applicationContext.xml.
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.security.filterChains': Cannot resolve reference to bean 'org.springframework.security.web.DefaultSecurityFilterChain#0' while setting bean property 'sourceList' with key [0]; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.security.web.DefaultSecurityFilterChain#0': Cannot resolve reference to bean 'metadataGeneratorFilter' while setting constructor argument with key [0]; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'metadataGeneratorFilter' defined in ServletContext resource [/WEB-INF/applicationContext.xml]: Cannot resolve reference to bean 'metadata' while setting bean property 'metadataManager'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'metadata' defined in ServletContext resource [/WEB-INF/applicationContext.xml]: Cannot create inner bean 'org.springframework.security.saml.metadata.ExtendedMetadataDelegate#62577c5e' of type [org.springframework.security.saml.metadata.ExtendedMetadataDelegate] while setting constructor argument with key [0]; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.security.saml.metadata.ExtendedMetadataDelegate#62577c5e' defined in ServletContext resource [/WEB-INF/applicationContext.xml]: Cannot create inner bean 'org.opensaml.saml2.metadata.provider.HTTPMetadataProvider#4b94ba17' of type [org.opensaml.saml2.metadata.provider.HTTPMetadataProvider] while setting constructor argument; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.opensaml.saml2.metadata.provider.HTTPMetadataProvider#4b94ba17' defined in ServletContext resource [/WEB-INF/applicationContext.xml]: Could not resolve matching constructor (hint: specify index/type/name arguments for simple parameters to avoid type ambiguities)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:334)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:108)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveManagedList(BeanDefinitionValueResolver.java:358)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:157)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1419)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1160)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:517)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:293)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:223)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:290)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:191)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:620)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:942)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:482)
at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:410)
at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:306)
at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:112)
at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4651)
at org.apache.catalina.core.StandardContext$1.call(StandardContext.java:5154)
at org.apache.catalina.core.StandardContext$1.call(StandardContext.java:5149)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
at java.util.concurrent.FutureTask.run(FutureTask.java:138)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:895)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:918)
at java.lang.Thread.run(Thread.java:662)
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.security.web.DefaultSecurityFilterChain#0': Cannot resolve reference to bean 'metadataGeneratorFilter' while setting constructor argument with key [0];
ApplicationContext.xml:
<beans:beans xmlns="###############/schema/security"
xmlns:beans="###############/schema/beans"
xmlns:xsi="###############/XMLSchema-instance"
xsi:schemaLocation="
###############/schema/security
###############/schema/security/spring-security-3.2.xsd
###############/schema/beans
###############/schema/beans/spring-beans-3.0.xsd">
<http entry-point-ref="samlEntryPoint">
<intercept-url pattern="/login.xhtml" access="permitAll"/>
<intercept-url pattern="/**" access="isAuthenticated()"/>
<custom-filter before="FIRST" ref="metadataGeneratorFilter"/>
<custom-filter after="BASIC_AUTH_FILTER" ref="samlFilter"/>
</http>
<beans:bean id="samlEntryPoint" class="org.springframework.security.saml.SAMLEntryPoint">
<beans:property name="defaultProfileOptions">
<beans:bean class="org.springframework.security.saml.websso.WebSSOProfileOptions">
<beans:property name="includeScoping" value="false"/>
</beans:bean>
</beans:property>
</beans:bean>
<beans:bean id="samlFilter" class="org.springframework.security.saml.SAMLProcessingFilter">
<beans:property name="authenticationManager" ref="authenticationManager"/>
</beans:bean>
<beans:bean id="metadataGeneratorFilter" class="org.springframework.security.saml.metadata.MetadataGeneratorFilter">
<beans:constructor-arg>
<beans:bean class="org.springframework.security.saml.metadata.MetadataGenerator">
<beans:property name="entityId" value="###################"/>
<beans:property name="extendedMetadata">
<beans:bean class="org.springframework.security.saml.metadata.ExtendedMetadata">
<beans:property name="idpDiscoveryEnabled" value="false"/>
</beans:bean>
</beans:property>
</beans:bean>
</beans:constructor-arg>
<beans:property name="metadataManager" ref="metadata"/>
</beans:bean>
<authentication-manager alias="authenticationManager">
<authentication-provider ref="samlAuthenticationProvider"/>
</authentication-manager>
<beans:bean id="samlAuthenticationProvider" class="org.springframework.security.saml.SAMLAuthenticationProvider"/>
<beans:bean id="samlLogger" class="org.springframework.security.saml.log.SAMLDefaultLogger"/>
<beans:bean id="samlContextProvider" class="org.springframework.security.saml.context.SAMLContextProviderImpl"/>
<beans:bean id="webSSOprofile" class="org.springframework.security.saml.websso.WebSSOProfileImpl"/>
<beans:bean id="webSSOprofileECP" class="org.springframework.security.saml.websso.WebSSOProfileECPImpl"/>
<beans:bean id="logoutProfile" class="org.springframework.security.saml.websso.SingleLogoutProfileImpl"/>
<beans:bean id="processor" class="org.springframework.security.saml.processor.SAMLProcessorImpl">
<beans:constructor-arg>
<beans:list>
<beans:bean class="org.springframework.security.saml.processor.HTTPRedirectDeflateBinding"/>
<beans:bean class="org.springframework.security.saml.processor.HTTPPostBinding"/>
<beans:bean class="org.springframework.security.saml.processor.HTTPArtifactBinding">
<beans:constructor-arg>
<beans:list>
<beans:bean class="org.springframework.security.saml.websso.ArtifactResolutionProfileImpl"/>
</beans:list>
</beans:constructor-arg>
</beans:bean>
<beans:bean class="org.springframework.security.saml.processor.HTTPSOAP11Binding"/>
<beans:bean class="org.springframework.security.saml.processor.HTTPPAOS11Binding"/>
</beans:list>
</beans:constructor-arg>
</beans:bean>
<beans:bean id="metadata" class="org.springframework.security.saml.metadata.CachingMetadataManager">
<beans:constructor-arg>
<beans:list>
<beans:bean class="org.springframework.security.saml.metadata.ExtendedMetadataDelegate">
<beans:constructor-arg index="0">
<beans:bean class="org.opensaml.saml2.metadata.provider.HTTPMetadataProvider">
<beans:constructor-arg index="0" ref="httpClient"/>
<beans:constructor-arg index="1" value="https://login.microsoftonline.com/##############/federationmetadata/2007-06/federationmetadata.xml"/>
<beans:constructor-arg index="2" type="int" value="15000"/> <!-- Timeout in milliseconds -->
<beans:property name="parserPool" ref="parserPool"/>
</beans:bean>
</beans:constructor-arg>
<beans:constructor-arg index="1">
<beans:bean class="org.springframework.security.saml.metadata.ExtendedMetadata"/>
</beans:constructor-arg>
</beans:bean>
</beans:list>
</beans:constructor-arg>
</beans:bean>
<beans:bean id="parserPool" class="org.opensaml.xml.parse.BasicParserPool" init-method="initialize">
<beans:property name="builderFeatures">
<beans:map>
<beans:entry key="http://apache.org/xml/features/dom/defer-node-expansion" value="false"/>
</beans:map>
</beans:property>
</beans:bean>
<beans:bean id="metadataGenerator" class="org.springframework.security.saml.metadata.MetadataGenerator">
<beans:property name="entityId" value="###################"/> <!-- Application (client) ID -->
<beans:property name="extendedMetadata">
<beans:bean class="org.springframework.security.saml.metadata.ExtendedMetadata">
<beans:property name="idpDiscoveryEnabled" value="false"/>
</beans:bean>
</beans:property>
</beans:bean>
<beans:bean id="httpClient" class="org.apache.commons.httpclient.HttpClient"/>
</beans:beans>
web.xml:
<web-app xmlns="###############/xml/ns/javaee"
xmlns:xsi="###############/2001/XMLSchema-instance"
xsi:schemaLocation="###############/xml/ns/javaee
###############/xml/ns/javaee/web-app_2_5.xsd"
version="2.5">
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<welcome-file-list>
<welcome-file>index.xhtml</welcome-file>
</welcome-file-list>
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.xhtml</url-pattern>
</servlet-mapping>
</web-app>
pom.xml:
<project xmlns="###############/POM/4.0.0"
xmlns:xsi="###############/2001/XMLSchema-instance"
xsi:schemaLocation="###############/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>saml-jsf-demo</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<dependencies>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.0.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.opensaml</groupId>
<artifactId>opensaml-core</artifactId>
<version>3.1.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.security.extensions/spring-security-saml2-core -->
<dependency>
<groupId>org.springframework.security.extensions</groupId>
<artifactId>spring-security-saml2-core</artifactId>
<version>1.0.1.RELEASE</version>
</dependency>
<dependency>
<groupId>commons-httpclient</groupId>
<artifactId>commons-httpclient</artifactId>
<version>3.1</version>
</dependency>
<dependency>
<groupId>javax.faces</groupId>
<artifactId>jsf-api</artifactId>
<version>2.1</version>
</dependency>
<dependency>
<groupId>org.glassfish</groupId>
<artifactId>javax.faces</artifactId>
<version>2.1.6</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-core</artifactId>
<version>3.2.10.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>3.2.10.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>3.2.10.RELEASE</version>
</dependency>
</dependencies>
<build>
<finalName>saml-jsf-demo</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.1.1</version>
</plugin>
</plugins>
</build>
</project>
This is a small example project so that I can insert SAML into my application that uses Java 6 + JSF and runs on WebSphere 7.
I omitted some URLs because StackOverFlow understood it was SPAM =(
CBL is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.