7 Replies Latest reply: Jan 9, 2013 8:31 AM by 870199 RSS

    problems with JAX-WS when using security (e.g. username token profile)

    870199
      Hello,
      I have a JAX-WS 2.1.5 deployed on weblogic 11g (10.3.1) with this policy:

      <wsp:UsingPolicy wssutil:Required="true"/>
      <wsp:Policy wssutil:Id="Hdm-UserNameToken-Plain">
      <ns1:SupportingTokens xmlns:ns1="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200512">
      <wsp:Policy>
      <ns1:UsernameToken ns1:IncludeToken="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200512/IncludeToken/AlwaysToRecipient">
      <wsp:Policy>
      <ns1:WssUsernameToken10/>
      </wsp:Policy>
      </ns1:UsernameToken>
      </wsp:Policy>
      </ns1:SupportingTokens>
      </wsp:Policy>

      I have another web application as client which is using a JAX-WS SOAP handler to communicate with web service
      and everything works fine when my client runs in stand-alone manner i.e. in Eclipse (JDK 6) (anthentication goes through)

      The handleMessage() method of my handler is posted here :
      public boolean handleMessage(SOAPMessageContext context) {
           final Boolean outbound = (Boolean) context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
      if (outbound)
      try {
      // Get the SOAP Envelope
      final SOAPEnvelope envelope = context.getMessage().getSOAPPart().getEnvelope();

      // Header may or may not exist
      SOAPHeader header = envelope.getHeader();
      if (header == null)
      header = envelope.addHeader();

      // Add WSS Usertoken Element Tree
      final SOAPElement security = header.addChildElement("Security", "wsse", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd");
      final SOAPElement userToken = security.addChildElement("UsernameToken", "wsse");
      userToken.addChildElement("Username", "wsse").addTextNode(userName);
      userToken.addChildElement("Password", "wsse").addTextNode(password);

      }
      catch (SOAPException ex) {
      ex.printStackTrace();
      return false;
      }

      return true;
      }

      but when I deploy the same client on weblogic server it fails to communicate with my web service with this error:
      javax.xml.ws.soap.SOAPFaultException: Unable to add security token for identity, token uri =http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#UsernameToken

      I noticed Weblogic has some packages to handle security like:
      weblogic.wsee.security.unt.ClientUNTCredentialProvider
      weblogic.xml.crypto.wss.provider.CredentialProvider
      weblogic.xml.crypto.wss.WSSecurityContext

      So I added another mechanism using weblogic package to add username password to SOAP header

      Map<String, Object> request = ((BindingProvider) proxy).getRequestContext();
      if (connectInfo.get("username") != null && connectInfo.get("password") != null) {
      List<CredentialProvider> credProviders = new ArrayList<CredentialProvider>();
      //client side UsernameToken credential provider
      CredentialProvider cp = new ClientUNTCredentialProvider((String)connectInfo.get("username"),
      (String)connectInfo.get("password"));
      credProviders.add(cp);
      request.put(WSSecurityContext.CREDENTIAL_PROVIDER_LIST, credProviders);
      }

      This seems to be ok but only for weblogic.

      I don't want to use weblogic propritery style in my client code i.e. using APIs ClientUNTCredentialProvider, WSSecurityContext etc, because for these to use i would need to have Weblogic jar which would cause me another issues..

      Is this an incompatibly issue or am i missing something, please suggest how to add security token for identity in SOAPHeader without using Weblogic specific APIs??
        • 1. Re: problems with JAX-WS when using security (e.g. username token profile)
          870199
          Also, adding to above details, i tried below too but NO help:

          final SOAPEnvelope envelope = context.getMessage().getSOAPPart().getEnvelope();
          SOAPHeader header = envelope.getHeader();
          final SOAPElement security = header.addHeaderElement(envelope.createName("Security", "wsse", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"));
          final SOAPElement userToken = security.addChildElement("UsernameToken", "wsse");
          userToken.addChildElement("Username", "wsse").addTextNode(userName);
          userToken.addChildElement("Password", "wsse").addTextNode(password);

          i.e. instead of using 'addHeaderElement' i tried addHeaderElement, but No luck, got the same issue... in handleMessage(....) method i tried to print SOAPHeader, SOAPEnvelope etc after the processing and i got below:

          userToken ---------> [wsse:UsernameToken: null]

          envelope ---------> [S:Envelope: null]

          header ---------> [S:Header: null]
          • 2. Re: problems with JAX-WS when using security (e.g. username token profile)
            User696-Oracle
            1)Edit WSDL file on client side

            Comment the PolicyReference under the binding element
            <wsp:PolicyReference URI="#XXXXX_Policy.xml"/>

            .
            2)Edit client code were your creating Service object
            For Example: helloImplService = new HelloImplService(HelloImplPortClient.class.getResource("HelloImplService.wsdl"), new QName("http://examples.webservices.hello_jws/","HelloImplService"));

            3)You may change the ws endpoint url by adding this line:
            requestContext.put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY,"https://localhost:7002/HelloImpl/HelloImplService");

            See if that works.

            Regards,
            Sunil P
            • 3. Re: problems with JAX-WS when using security (e.g. username token profile)
              870199
              Many thanks Sunil for quick response, i will try it out!

              Rgds,
              • 4. Re: problems with JAX-WS when using security (e.g. username token profile)
                User696-Oracle
                1. Commenting "<wsp:PolicyReference....../>" would mean, i will be able to call my web-service without uname and pwd?
                You will comment on the client side WSDL but the server side wsdl should still have the reference <wsp:PolicyReference....../> and use the SOAP handler code to populate username and password.

                2. Do you have any sample code which reads a WSDL URL and edit it, if yes could you please share??
                You need not read it from url you can copy the wsdl file on local machine and edit it and pass this wsdl file on client side, i do not have any code.


                3. Is 3rd step mandatory?
                If you have right value inside the <soap:address location="http://localhost:7001/contextroot/app"/> you need not require it

                Regards,
                Sunil P
                • 5. Re: problems with JAX-WS when using security (e.g. username token profile)
                  870199
                  Indeed solution you gave worked for me :-)

                  With following two changes in WSDL:

                  1. Commenting "<wsp:PolicyReference....../>" [This is fine -- One time job]

                  updating the wsdl manually and using for my purpose does not look like the right approach, Is there NO other way of doing this??
                  • 6. Re: problems with JAX-WS when using security (e.g. username token profile)
                    User696-Oracle
                    I am glad it worked, please mark the pst which had helped so that it benefits others, I can only think of that solution. If you do not want to change the <soap12:address you might using ENDPOINT_ADDRESS_PROPERTY

                    http://jax-ws.java.net/articles/MessageContext.html
                    http://tugdualgrall.blogspot.com/2009/02/jax-ws-how-to-configure-service-end_17.html

                    Regards,
                    Sunil P
                    • 7. Re: problems with JAX-WS when using security (e.g. username token profile)
                      870199
                      Yes, indeed, i had done the same, I did not have to modify XML for that rather i did following:

                      final Binding binding = ((BindingProvider) wsService).getBinding();
                      List<Handler> handlerList = binding.getHandlerChain();
                      if (handlerList == null)
                           handlerList = new ArrayList<Handler>();

                      handlerList.add(new WsSecuritySOAPHandler(username, password));
                      binding.setHandlerChain(handlerList);

                      BindingProvider bindingProvider = (BindingProvider) wsService;
                      Map<String,Object> rc = (Map<String,Object>)bindingProvider.getRequestContext();
                      rc.put(BindingProvider.USERNAME_PROPERTY, username);
                      rc.put(BindingProvider.PASSWORD_PROPERTY, password);
                      rc.put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, wsdlURL.substring(0, wsdlURL.length() - "?WSDL".length()));