3 Replies Latest reply on Oct 13, 2009 12:07 PM by Stefan B.

    JAX-WS Web Service Authentication (NTLM) against a MS CRM Se

    Ivan Stefanov Newbie

      Hello everybody,

      I am currently developing a jboss web service client, which is supposed to connect to a web service on a Microsoft CRM Dynamics (I hope I've got the name right) instance, running on an Internet Information Server. The service itself and the relevant data types are defined in a what appears to be a standard CrmServiceWsdl.aspx file.

      I've generated the Java classes with the /bin/wsconsume.bat tool in the JBoss folder. We have many times used this tool successfully, when programming JBoss web services and clients for them. Everything seemed nice and well, the client easily connected (including HTTP BASIC authentication) and sent what looked like a correct request to a dummy JBoss web service which I wrote for testing purposes. The problems appeared when we tried the real thing, namely connecting to the MS CRM web service. The IIS Server has the "Windows Intergrated Security" authentication activated, which is supposed to be NTLM.

      First I have tried doing HTTP Basic, as the IIS was also supposed to support it:

      url = new java.net.URL(InfondsParameter.CRMWebServiceUrlCreateUpdateTask.get(em));
      
      CrmTaskServiceSoap port = (new CrmTaskService(url, new QName("http://schemas.microsoft.com/crm/2007/WebServices", "CrmService")))
      .getCrmTaskServiceSoap();
      ((BindingProvider)port).getRequestContext().put(BindingProvider.USERNAME_PROPERTY, "username");
      ((BindingProvider)port).getRequestContext().put(BindingProvider.USERNAME_PROPERTY, "password");
      


      This didn't work and I kept getting the "javax.xml.ws.WebServiceException: org.jboss.ws.WSException: Target endpoint address not set" error message plus debug messages (my own) telling me the WSDL could not be reached.

      Then I decided to aim for the NTLM authentication. Following advice I found on many (non official) sources in Internet, I wrote the following:

      static class MyAuthenticator extends Authenticator {
      
       private String user;
       private String pass;
      
       public MyAuthenticator(String user, String pass) {
       this.user = user;
       this.pass = pass;
       }
      
       public PasswordAuthentication getPasswordAuthentication() {
       return (new PasswordAuthentication(kuser, kpass.toCharArray()));
       }
       }
      
      public static void callCreateTask()
      
       Authenticator.setDefault(new MyAuthenticator("username", "password"));
      
       url = new java.net.URL(InfondsParameter.CRMWebServiceUrlCreateUpdateTask.get(em));
      
       CrmTaskServiceSoap port = (new CrmTaskService(url, new QName("http://schemas.microsoft.com/crm/2007/WebServices", "CrmService")))
      .getCrmTaskServiceSoap();
      
      ...
      
       String ret = port.create(ent);
      }
      


      Now the WSDL seems to get reached and consumed, but at the last row I still get a "org.jboss.ws.WSException: Invalid HTTP server response [401] - Unauthorized". The port.create(ent) statement is just calling the "create" operation, defined in the WSDL, with the argument being an entity, also as defined in the WSDL.

      I really fail to grasp what is going wrong. As far as I know, Java is supposed to support NTLM Authentication "off the shelf" through the Authenticator class and it obviously does some work, as the WSDL residing on the IIS could be opened and read. However, the call to the service itself could not be authorised. I've found some references to a CrmAuthenticationToken having to be set, but neither my CrmTaskService (which is the standard CrmService), nor CrmTaskServiceSoap (which is the proxy of the service) has been generated with a possibility to set Credentials or AuthenticationToken.

      Has anyone had exprience with interfacing the Microsoft CRM Web Services? Any advice, insight or ideas are welcome!

      Thank you in advance!

      Best regards,
      Ivan Stefanov

        • 1. Re: JAX-WS Web Service Authentication (NTLM) against a MS CR
          fake fake Newbie

          I working with NTLM in a different scenario, and it seems that NTLM doesn't work when chunking is used by the client. Do a sniff on your traffic to see what is going on. If you have the appropriate jbossws version you can turn chunking off (http://www.jboss.org/community/wiki/JBossWS-NativeUserGuide#Chunked_encoding_setup). if You are using 3.2.0 I'm curious as to your results (i am using an older version and still searching for a way to disable chunking).

          see my thread at http://www.jboss.org/index.html?module=bb&op=viewtopic&t=160737 for a bigger explanation of my findings.

          When the client is using chunking, it seems like the jvm doesn't recognize the 401 that is returned from the server before it sends the first chunk and thus never calls our custom authenticators. When chunking is not used, the client sends its whole request at once and then waits for the response (which is a 401) that triggers the authentication sequence. That's my theory anyway.

          GL

          • 2. Re: JAX-WS Web Service Authentication (NTLM) against a MS CR
            fake fake Newbie

            I fixed my problem by disabling chunking by reverting the client to a different configuration, you could try:

            CrmTaskServiceSoap port = (new CrmTaskService(url, new QName("http://schemas.microsoft.com/crm/2007/WebServices", "CrmService")))
            .getCrmTaskServiceSoap();
            
            ...
            
            ((StubExt) port).setConfigName("HTTP 1.0 Client");
            
            String ret = port.create(ent);
            
            


            • 3. Re: JAX-WS Web Service Authentication (NTLM) against a MS CR
              Stefan B. Newbie

              Hi,

              i want to access the M$ CRM, too. I get the same 401 Unauthorized Execption.

              Using: JBossWS 3.2.0 (nativ)

              Exception in thread "main" com.sun.xml.ws.client.ClientTransportException: request requires HTTP authentication: Unauthorized
               at com.sun.xml.ws.transport.http.client.HttpClientTransport.checkResponseCode(HttpClientTransport.java:212)
               at com.sun.xml.ws.transport.http.client.HttpTransportPipe.process(HttpTransportPipe.java:149)
               at com.sun.xml.ws.transport.http.client.HttpTransportPipe.processRequest(HttpTransportPipe.java:86)
               at com.sun.xml.ws.api.pipe.Fiber.__doRun(Fiber.java:595)
               at com.sun.xml.ws.api.pipe.Fiber._doRun(Fiber.java:554)
               at com.sun.xml.ws.api.pipe.Fiber.doRun(Fiber.java:539)
               at com.sun.xml.ws.api.pipe.Fiber.runSync(Fiber.java:436)
               at com.sun.xml.ws.client.Stub.process(Stub.java:248)
               at com.sun.xml.ws.client.sei.SEIStub.doProcess(SEIStub.java:135)
               at com.sun.xml.ws.client.sei.SyncMethodHandler.invoke(SyncMethodHandler.java:109)
               at com.sun.xml.ws.client.sei.SyncMethodHandler.invoke(SyncMethodHandler.java:89)
               at com.sun.xml.ws.client.sei.SEIStub.invoke(SEIStub.java:118)
               at $Proxy24.retrieveMultiple(Unknown Source)
               at test.JBossWS.main(JBossWS.java:189)
              


              I sniff the network for checking the chunking issue, but it is disabled.

              POST /MSCrmServices/2007/CrmService.asmx HTTP/1.1
              SOAPAction: "http://schemas.microsoft.com/crm/2007/WebServices/RetrieveMultiple"
              Content-Type: text/xml;charset="utf-8"
              Accept: text/xml, multipart/related, text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
              User-Agent: JAX-WS RI 2.1.3-b02-
              Host: 10.10.10.1:3000
              Connection: keep-alive
              Content-Length: 413
              Authorization: NTLM TlRMTVNTUAABAAAAB4IIogAAAAAAAAAAAAAAAAAAAAAFASgKAAAADw==
              
              <?xml version='1.0' encoding='UTF-8'?>
               <S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
               <S:Body>
               <RetrieveMultiple xmlns="http://schemas.microsoft.com/crm/2007/WebServices" xmlns:ns2="http://schemas.microsoft.com/crm/2006/Query" xmlns:ns3="http://schemas.microsoft.com/crm/2006/WebServices">
               <query>
               <ns2:EntityName>LEAD</ns2:EntityName>
               <ns2:ColumnSet/>
               </query>
               </RetrieveMultiple>
               </S:Body>
               </S:Envelope>
              


              HTTP/1.1 401 Unauthorized
              Content-Length: 51
              Content-Type: text/plain
              Server: Microsoft-IIS/6.0
              WWW-Authenticate: NTLM TlRMTVNTUAACAAAAEAAQADgAAAAFgomidBgBvxAJL2AAAAAAAAAAAKYApgBIAAAABQLODgAAAA9HAEEATABBAFgASQBTADQAAgAQAEcAQQBMAEEAWABJAFMANAABAA4ASgBVAFAASQBUAEUAUgAEABwAZwBhAGwAYQB4AGkAcwA0AC4AbABvAGMAYQBsAAMALABKAFUAUABJAFQARQBSAC4AZwBhAGwAYQB4AGkAcwA0AC4AbABvAGMAYQBsAAUAHABnAGEAbABhAHgAaQBzADQALgBsAG8AYwBhAGwABwAIAKilKVgeTMoBAAAAAA==
              X-Powered-By: ASP.NET
              Date: Tue, 13 Oct 2009 16:00:53 GMT
              
              HTTP Error 401.1 - Unauthorized: Access is denied
              HTTP/1.1 401 Unauthorized
              Date: Tue, 13 Oct 2009 16:00:54 GMT
              Server: Microsoft-IIS/6.0
              WWW-Authenticate: Negotiate
              WWW-Authenticate: NTLM
              X-Powered-By: ASP.NET
              X-AspNet-Version: 2.0.50727
              Cache-Control: private
              Content-Length: 0
              


              Have any one an idea or link with a solution?

              Greetz,

              Clash