SpringSecurity-SAML(OpenSAML): Failed to unmarshall assertion: getting org.w3c.dom.DOMException: WRONG_DOCUMENT_ERR - spring-saml

Using spring-security-saml for handling assertions from IDP, getting below error after server is up for 1 to 2 hours. Issue is not reproducible all the time. By looking at stacktrace, issue seems to be related to parser pool used in spring saml configuration. Please share any thoughts.
library versions:
opensaml 2.6.1
spring-security-saml2 1.0.0.RELEASE
parser pool config:
<bean id="parserPool" class="org.opensaml.xml.parse.StaticBasicParserPool" init-method="initialize">
<property name="builderFeatures">
<map>
<entry key="http://apache.org/xml/features/dom/defer-node-expansion" value="false"/>
</map>
</property>
</bean>
<bean id="parserPoolHolder" class="org.springframework.security.saml.parser.ParserPoolHolder"/>
The stack trace is:
org.w3c.dom.DOMException: WRONG_DOCUMENT_ERR: A node is used in a different document than the one that created it.
at org.apache.xerces.dom.ParentNode.internalInsertBefore(Unknown Source)
at org.apache.xerces.dom.ParentNode.insertBefore(Unknown Source)
at org.apache.xerces.dom.NodeImpl.appendChild(Unknown Source)
at org.opensaml.xml.encryption.Decrypter.parseInputStream(Decrypter.java:821)
at org.opensaml.xml.encryption.Decrypter.decryptDataToDOM(Decrypter.java:599)
at org.opensaml.xml.encryption.Decrypter.decryptUsingResolvedEncryptedKey(Decrypter.java:784)
at org.opensaml.xml.encryption.Decrypter.decryptDataToDOM(Decrypter.java:524)
at org.opensaml.xml.encryption.Decrypter.decryptDataToList(Decrypter.java:442)
at org.opensaml.xml.encryption.Decrypter.decryptData(Decrypter.java:403)
at org.opensaml.saml2.encryption.Decrypter.decryptData(Decrypter.java:141)
at org.opensaml.saml2.encryption.Decrypter.decrypt(Decrypter.java:69)
at org.springframework.security.saml.websso.WebSSOProfileConsumerImpl.processAuthenticationResponse(WebSSOProfileConsumerImpl.java:199)
at org.springframework.security.saml.SAMLAuthenticationProvider.authenticate(SAMLAuthenticationProvider.java:82)

Root cause: Multiple implementations of xerces in the project.
Found the issue. My project also has docx4j used for word document processing, docx4j changed the system property javax.xml.parsers.DocumentBuilderFactory to "com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl" when it is initialized and if system property is not already set and java version < 8, which internally caused to return a DocumentBuilderFactory implementation that is different from the one opensaml was initialized with. i.e org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl
Fix is setting system property javax.xml.parsers.DocumentBuilderFactory to com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl by using following java runtime option
-Djavax.xml.parsers.DocumentBuilderFactory=com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl

As #Srini said, the root cause is multiple implementations of xerces in the project.
I solved this by overriding the docx4j properties in docx4j.properties:
javax.xml.parsers.DocumentBuilderFactory=org.apache.xerces.jaxp.DocumentBuilderFactoryImpl

Related

Blueprint/Spring can't find 'classpath:path/to/file.ext' resource having moved project from Talend 6.5.1 to 7.1.1

In a Talend ESB (SE) project, I have a bean instantiated in the "Spring" configuration using a route resource.
In version 6.5.1 the following (used as a parameter) works fine.
<bean class="java.lang.String">
<constructor-arg>
<bean class="org.springframework.util.FileCopyUtils" factory-method="copyToByteArray" >
<constructor-arg value="classpath:query/sqlQuery.sql" type="java.io.InputStream" />
</bean>
</constructor-arg>
</bean>
but this doesn't for in my Talend 7.1.1 project. It seems to be unable to find the resource. I've looked in the created .kar file, and the resource is in the project .jar in the query folder.
[EDIT] It appears that Talend 7.1.1 encloses the "Spring" configuration in a <blueprint> element, which perhaps has change the way in which this functions.
I presume that something has changed in the way Talend packages the route, or in the way that the Spring xml is interpreted. Camel has no problem finding resources, for example from("sql:classpath:query/sqlQuery.sql"), but the "Spring" classpath search seems not to be able to find them.
I've tried substituting classpath*: for the straight classpath in the parameter as that had been suggested in some of the answers I'd seen to "resource not found" questions, but this didn't seem to be valid and was interpreted as a straight filename.
Am I doing something wrong with the classpath declaration? Is there another way of setting a spring/blueprint bean property with the contents of a resource file?
I've also tried explicitly declaring a ClassPathResource bean and it claims the resource does not exist when using the getInputStream() method, despite the fact I can see it if I open up the contained jar file.
Has the wrapping of the created feature in Maven terms (from Talend 7) had some impact on the classpath I need to use?

Programatically set v$session program property

I found some answers on the problem but none that i could make work in my case. My problem is that I load a datasource from my JBoss configuration with spring:
<xa-datasource jndi-name="java:jboss/jdbc/oracleDatasource" pool-name="jdbc/oracleDatasource" enabled="true">
<xa-datasource-property name="URL">
jdbc:oracle:thin:#URL:1522:SID
</xa-datasource-property>
<xa-datasource-property name="connectionProperties">
v$session.program=MyAPP
</xa-datasource-property>
<driver>oracle-jdbc</driver>
The spring loading is made as follows:
<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="java:jboss/jdbc/oracleDatasource"/>
</bean>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<constructor-arg ref="dataSource"/>
</bean>
As you can see, I have set the v$session.program property in JBoss, it works well.
The problem is that i have several applications (war) that can be deployed on the same JBoss server, using this configuration. What I want to do in this case is to have each of my application to have its own name written in the v$session.program property.
So basically, i would like to be able to load the same datasource on each app but to have each of them using its own name to log the program property in oracle DB. Is it possible or do I have to have one datasource for each application hosted?
The only thing you need it to intercept each call of getConnection from connection pool.
You must obtain a real Oracle connection - not a proxy - and call the setClientInfo on 12c or setEndToEndMetrics in older versions to set the action / client / module identification.
An example see here.
Also note that the use of dbms_application_info for this same purpose works as well, but this produces a one server roundtrip too much. The setClientInfo doesn't produce server call, but stores this information for the next statement execution (which is the preformance saving approach).
Also note that to use this feature, your driver must match perfectly with your database - the strange exeptions you can see while setting teh client info are in most cases caused by the incompatibility of teh JDBC driver and the RDBMS.
If putting this information into v$session.module or v$session.client_info is an option, you can do using Java code.
All you need to do is call dbms_application_info.set_module() or dbms_application_info.set_client_info() after your Java code obtained the connection from the datasource.
Something like this:
Connection conn = ... // get connection from the DataSource
CallableStatement cstmt = conn.prepareCall("{call dbms_application_info.set_client_info(?)}");
cstmt.setString(1, "Some interesting information");
cstmt.execute();

Spring session with JDBC integration

I am new in Spring Session and want to use embedded database to store session information. I follow all the steps in
http://docs.spring.io/spring-session/docs/current/reference/html5/guides/httpsession-jdbc.html using spring-session-jdbc of version 1.2.0.but using Spring-web of 3.2.4 only
The following error is shown repeatly:
Caused by: org.postgresql.util.PSQLException: ERROR: relation "spring_session" does not exist 'Position: 13
at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2198)
at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:1927)
at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:255)
at org.postgresql.jdbc2.AbstractJdbc2Statement.execute(AbstractJdbc2Statement.java:561)
at org.postgresql.jdbc2.AbstractJdbc2Statement.executeWithFlags(AbstractJdbc2Statement.java:419)
at org.postgresql.jdbc2.AbstractJdbc2Statement.executeUpdate(AbstractJdbc2Statement.java:365)
at com.mchange.v2.c3p0.impl.NewProxyPreparedStatement.executeUpdate(NewProxyPreparedStatement.java:105)
at org.springframework.jdbc.core.JdbcTemplate$2.doInPreparedStatement(JdbcTemplate.java:824)
at org.springframework.jdbc.core.JdbcTemplate$2.doInPreparedStatement(JdbcTemplate.java:818)
at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:589)
... 21 more'
This issue already haunted me for days. Please help.
Here is the xml configuration
<bean class="org.springframework.session.jdbc.config.annotation.web.http.JdbcHttpSessi‌​onConfiguration"/>
<jdbc:embedded-database id="dataSource02" type="H2">
<jdbc:script location="classpath:org/springframework/session/jdbc/schema-h2.sql"/>
</jdbc:embedded-database>
<bean class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<constructor-arg ref="dataSource02"/>
</bean>
Your problem stems from the fact that you use multiple data sources, since the provided stacktrace includes PostgreSQL JDBC driver classes while you are configuring a secondary, embedded data source to storing sessions.
Spring Session configuration picks up your primary data source (PostgreSQL) and expects to find session tables there.
I'd suggest you to use your primary data source to store session data, but if you insist on having secondary/embedded data source for that purpose you need to override JdbcOperationsSessionRepository bean provided by JdbcHttpSessionConfiguration#sessionRepository with your own instance which is created using your secondary data source and its appropriate tra saction manager. Note that bean must be named sessionRepository in order to override one from JdbcHttpSessionConfiguration.

Spring JdbcTemplate ConnectionPooling Configuration

I am working on a Spring MVC application in which I have recently been convinced to revamp my database code. Before I was using very traditional JDBC code that I have been told was very "old school" because of the boilerplate code. I have been making the transition to using JdbcTemplate with Spring.
I have configured a bean like shown below in my applicationContext.xml file.
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:ip-address:port/dbName"/>
<property name="username" value="myUsername"/>
<property name="password" value="mypassword"/>
</bean>
I have run tests just to make sure everything is working and it is.
My question is, I am aware that I am using the Commons DBCP package which uses the
following packages
commons-dbcp package
commons-pool package
Again, I am very inexperienced with this, so I apologize if I am mis referencing something or am explaining something incorrectly.
I have followed what most of the tutorials have said to do and specified a jdbcTemplate and injected the dataSource bean into it, but this doesnt really refer to my question.
What I would really like to know is, am I using ConnectionPooling with this configuration?
If so, is it being done behind the scenes, or do I need to specify to do it somewhere?
I have looked at the documentation at Here which gives the following, but I am not sure exactly how to interpret it.
"here are several Database Connection Pools already available, both within Apache products and elsewhere. This Commons package provides an opportunity to coordinate the efforts required to create and maintain an efficient, feature-rich package under the ASF license.
The commons-dbcp package relies on code in the commons-pool package to provide the underlying object pool mechanisms that it utilizes."
I also looked at the Configuration Page
and based on this page, I would think that I am able to do ConnectionPooling, but may need to specify additional parameters in my dataSource bean.
Can somebody please answer my questions or point me in the right direction?
Yes you are using connection pooling.
here is another thread you might find interesting
http://forum.springsource.org/showthread.php?t=40598
Also most of the links you specified above will provide additional information on parameters that can be set.

Loading Liferay Properties from Spring IoC container (to get jdbc connection parameters)

I'm developing some portlets for Liferay Portal 5.2.3 with bundled tomcat 6.0.18 using Spring IoC container.
I need to map the User_ table used in Liferay database to an entity with Hibernate, so I need to use two different dataSources to separate the liferay db from the db used by portlets.
My jdbc.properties has to hold all connection parameters for both databases: no problem for the one used by portlets, but I am having issues determining which database uses liferay to hold its data.
My conclusion is that i should have something like this:
liferayConnection.url=jdbc:hsqldb:${liferay.home}/data/hsql/lportal
in order to get the database url dynamically loaded, according to Liferay properties found in portal-ext.properties. (Or, better, load the whole portal-ext.properties and read database properties from there).
The problem is that the placeholder is not resolved:
Caused by: org.springframework.beans.factory.BeanDefinitionStoreException: Invalid bean definition with name 'liferayDataSource' defined in class path resource [WEB-INF/applicationContext.xml]: Could not resolve placeholder 'liferay.home'
To dodge this problem I tried to load explicitly portal-ext.properties with a Spring bean:
<bean id="liferayPropertiesConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"
p:location="../../portal-ext.properties"/>
but no luck: liferay.home is not resolved but there aren't other errors.
How can I resolve the placeholder defined by Liferay? Thanks
You can use PropsUtil class (from Liferay) to get values of portal-ext.properties.
String value = PropsUtil.get("key");
For loading properties files from an applicationContext.xml file I usually use the PropertiesFactoryBean specifying the location property with a the name of the file located in the classpath, like this:
<bean name="myHibernateProperties" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="location">
<value>classpath:hibernate.properties</value>
</property>
</bean>
Make sure the properties files are in a folder/package that is in the classpath.
You can call PropsUtil using SpringEL. for example:
#{T(com.liferay.portal.kernel.util.PropsUtil).get('liferay.home')}
I haven't tried exactly this. but you could load the liferay properties that you need with the following:
<util:properties id="liferayProps">
<prop key="liferay.home">#{T(com.liferay.portal.kernel.util.PropsUtil).get('liferay.home')}</prop>
</util:properties>

Resources