2 Replies Latest reply on Nov 14, 2012 5:31 AM by Alessio Soldano

    SAML2 WSS4J Policy Handler Issue (org.w3c.dom.DOMException: WRONG_DOCUMENT_ERR)

    Andreas Triebel Newbie

      JBoss AS 7.1.1.Final

      JBoss Web Services - Stack CXF Server 4.1.0.Final

      picketlink-as7-2.1.5.Final

       

      Hi

       

      In a web service client I'd like to use the SAML2 assertion from the current subject and set it in the SAMLCallback (the SAML assertion was acquired via PL STSIssuingLoginModule).

       

      When processing the WS-security policy, I get following error from the CXF policy handler.

       

      09:06:16,139 ERROR [org.apache.catalina.core.ContainerBase.[jboss.web].[default-host].[/JBoss_WSClient_STSIssuingLM].[SAMLWebServiceClient]] (http-...) Servlet.service() for servlet SAMLWebServiceClient threw exception: javax.xml.ws.soap.SOAPFaultException: WRONG_DOCUMENT_ERR: A node is used in a different document than the one that created it.

          at org.apache.cxf.jaxws.JaxWsClientProxy.invoke(JaxWsClientProxy.java:156)

          at $Proxy44.doit(Unknown Source)    at ssotest.ws.SAMLWebServiceClientServlet.doGet(SAMLWebServiceClientServlet.java:62) [classes:]

          at javax.servlet.http.HttpServlet.service(HttpServlet.java:734) [jboss-servlet-api_3.0_spec-1.0.0.Final.jar:1.0.0.Final]

          at javax.servlet.http.HttpServlet.service(HttpServlet.java:847) [jboss-servlet-api_3.0_spec-1.0.0.Final.jar:1.0.0.Final]

          at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:329) [jbossweb-7.0.13.Final.jar:]

          at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:248) [jbossweb-7.0.13.Final.jar:]

          at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:275) [jbossweb-7.0.13.Final.jar:]

          at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:161) [jbossweb-7.0.13.Final.jar:]

          at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:489) [jbossweb-7.0.13.Final.jar:]

          at org.jboss.as.web.security.SecurityContextAssociationValve.invoke(SecurityContextAssociationValve.java:153) [jboss-as-web-7.1.1.Final.jar:7.1.1.Final]

          at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:155) [jbossweb-7.0.13.Final.jar:]

          at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102) [jbossweb-7.0.13.Final.jar:]

          at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109) [jbossweb-7.0.13.Final.jar:]

          at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:368) [jbossweb-7.0.13.Final.jar:]

          at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:877) [jbossweb-7.0.13.Final.jar:]

          at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:671) [jbossweb-7.0.13.Final.jar:]

          at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:930) [jbossweb-7.0.13.Final.jar:]

          at java.lang.Thread.run(Thread.java:662) [rt.jar:1.6.0_23]

      Caused by: 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(ParentNode.java:351)

          at org.apache.xerces.dom.ParentNode.insertBefore(ParentNode.java:283)

          at org.apache.xerces.dom.NodeImpl.appendChild(NodeImpl.java:236)

          at org.apache.cxf.ws.security.wss4j.policyhandlers.AbstractBindingBuilder.insertAfter(AbstractBindingBuilder.java:190)

          at org.apache.cxf.ws.security.wss4j.policyhandlers.AbstractBindingBuilder.addSupportingElement(AbstractBindingBuilder.java:232)

          at org.apache.cxf.ws.security.wss4j.policyhandlers.AbstractBindingBuilder.addSignatureParts(AbstractBindingBuilder.java:698)

          at org.apache.cxf.ws.security.wss4j.policyhandlers.AbstractBindingBuilder.addSupportingTokens(AbstractBindingBuilder.java:2126)

          at org.apache.cxf.ws.security.wss4j.policyhandlers.AsymmetricBindingHandler.doSignBeforeEncrypt(AsymmetricBindingHandler.java:144)

          at org.apache.cxf.ws.security.wss4j.policyhandlers.AsymmetricBindingHandler.handleBinding(AsymmetricBindingHandler.java:98)

          at org.apache.cxf.ws.security.wss4j.PolicyBasedWSS4JOutInterceptor$PolicyBasedWSS4JOutInterceptorInternal.handleMessage(PolicyBasedWSS4JOutInterceptor.java:165)

          at org.apache.cxf.ws.security.wss4j.PolicyBasedWSS4JOutInterceptor$PolicyBasedWSS4JOutInterceptorInternal.handleMessage(PolicyBasedWSS4JOutInterceptor.java:89)

          at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:262)

          at org.apache.cxf.endpoint.ClientImpl.doInvoke(ClientImpl.java:531)

          at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:464)

          at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:367)

          at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:320)

          at org.apache.cxf.frontend.ClientProxy.invokeSync(ClientProxy.java:89)

          at org.apache.cxf.jaxws.JaxWsClientProxy.invoke(JaxWsClientProxy.java:134)

          ... 18 more

       

       

      SAMLCallbackHandler:

       

      public class SAMLWebServiceClientServlet extends HttpServlet {
           protected void doGet(HttpServletRequest req, HttpServletResponse resp)
                     throws ServletException, IOException {

                SAML2TestService service = new SAML2TestService();
                SAML2TestPortType port = service.getSAML2TestPortTypePort();
                Map<String, Object> ctx = ((BindingProvider) port).getRequestContext();
                ctx.put(SecurityConstants.SAML_CALLBACK_HANDLER, new SAMLCallbackHandler());              
                String result = port.doit();
           }
      ...
          private class SAMLCallbackHandler implements CallbackHandler {

             
              public void handle(Callback[] callbacks) throws IOException,
                      UnsupportedCallbackException {
                  for (int i = 0; i < callbacks.length; i++) {
                      if (callbacks[i] instanceof SAMLCallback) {
                          SAMLCallback sc = (SAMLCallback) callbacks[i];
                         
                          Subject subject = org.jboss.security.SecurityContextAssociation.getSubject();
                          Set<SamlCredential> samlCreds = subject.getPublicCredentials(SamlCredential.class);
                          for (SamlCredential samlCred : samlCreds) {
                              try {
                                  Element assertionElement = samlCred.getAssertionAsElement();
                                  sc.setAssertionElement(assertionElement);                           
                              } catch (ProcessingException e) {
                                  e.printStackTrace();
                              }
                          }
                          break;
                      }
                  }
              }
          }
      }

       

      Debugging shows that org.apache.cxf.ws.security.wss4j.policyhandlers.AbstractBindingBuilder.addSignatureParts() adds the assertion to the security header without using Document.importNode() in case of an AssertionWrapper (in case of WSSecurityTokenHolder it would call clone() which uses Document.importNode())


      Is this a bug, or do I miss something? Probably there's a more elegant way to access the subject's SAML assertion from CXF?

       

      Thanks,

      Andreas