Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SOAP PHP with NTLM authentication #57

Open
ayalon opened this issue May 28, 2016 · 5 comments
Open

SOAP PHP with NTLM authentication #57

ayalon opened this issue May 28, 2016 · 5 comments
Assignees

Comments

@ayalon
Copy link

ayalon commented May 28, 2016

Hi
I'm trying to generate classes from a NTLM secured wsdl file. The only and best approach to do this is described here:
https://thomas.rabaix.net/blog/2008/03/using-soap-php-with-ntlm-authentication

It's a StreamWrapper and an extend SOAP Client class. As I already saw in the documentation, it seems to be quite easy to replace the SOAP Client class in the setting.

But what is the best way to use a stream wrapper? I have to execute these command before and communiaction with the server happens

$url = 'http://myIISServer.com/xmlservice?wsdl';

// we unregister the current HTTP wrapper
stream_wrapper_unregister('http');

// we register the new HTTP wrapper
stream_wrapper_register('http', 'MyServiceProviderNTLMStream') or die("Failed to register protocol");

// so now all request to a http page will be done by MyServiceProviderNTLMStream.
// ok now, let's request the wsdl file
// if everything works fine, you should see the content of the wsdl file
$client = new SoapClient($url, $options);

// but this will failed
$client->mySoapFunction();

// restore the original http protocole
stream_wrapper_restore('http');

Does someone has a hint for me what could be the best way to do this using this library?

@mikaelcom
Copy link
Member

Hi,

Currently there is no option to use your own SoapClient class to be used to load the WSDL in order to generate the package. In addition, if the WSDL is protected by NTLM then this will be an issue as the WSDL and the schemas are also loaded using file_get_contents and stream_context_create so this would mean that it would need to use the NTLM authentication.

I know that curl can be used to authenticate through NTLM, http://php.net/manual/en/curl.constants.php#constant.curlauth-ntlm. This is something you can find in https://github.com/jamesiarmes/php-ews/blob/composer/src/PhpEws/Ntlm/NtlmSoapClient.php for example.

I never had the possibility to try the NTLM authentication so I never had the chance to develop the code that would be the best (in my point of view) to request a SOAP Web Service behind a NTLM authentication.

If you have the possibility to create me an access, even with limited rights, it would be great so I could work on it.

You can contact me at [email protected],
Regards,

@mikaelcom mikaelcom self-assigned this May 28, 2016
@ayalon
Copy link
Author

ayalon commented May 28, 2016

I already have a working NTLM Authentication using the SoapClient and the modified StreamWrapper. The implementation is based on the article I have posted above. The gitrepo you posted is just implementing the method described by Thomas Rabaix.

I thought I could provide a different SOAP Client with the option "--soapclient"?

The only thing I don't know how to do is to change the StreamWrapper (which is indeed based on curl).

Unfortunatly my NTLM Webservice is tied to an Active Directory and I'm not the administrator. But maybe you have a good idea how to use the streamwrapper as decribed in the code above?

@mikaelcom
Copy link
Member

I thought I could provide a different SOAP Client with the option "--soapclient"?

Indeed, this is something that is not implemented yet and that could be done. But as I said, if your WSDL import/include other schemas, it uses file_get_contents (which uses stream_context_create to add basic auth for example) to retrieve the additional schemas. THis is somthing that will not work if you only specify a custom SoapClient. It would also need another option such as --ntlm-login and ntlm-password (and more?) to achieve this. Am I wrong?

So if I sumup, you'll have to create your own SoapClient with your own StreamWrapper that would be used instead of the native SoapClient. Moreover, the generator does not use directly the native SoapClient class but this SoapClient, so it would require you to create a class that extends the AbstractSoapClientBase in order to use your own SoapClient class implementation (which would inherit from the native PHP SoapClient class. An example is available in the PackageEws365 package.

Is it enough clear? Am I missing something?

@ayalon
Copy link
Author

ayalon commented May 31, 2016

It's absolutly correct. The implementation is very easy. You will just need the 3 parameters --ntlm-domain --ntlm-login and --ntlm-password. The NTLMSoapClient is just overriding one method. Here is my code based on the example:

class NTLMSoapClient extends SoapClient {
  function __doRequest($request, $location, $action, $version) {

    $headers = array(
      'Method: POST',
      'Connection: Keep-Alive',
      'User-Agent: PHP-SOAP-CURL',
      'Content-Type: text/xml; charset=utf-8',
      'SOAPAction: "'.$action.'"',
    );

    $this->__last_request_headers = $headers;
    $ch = curl_init($location);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
    curl_setopt($ch, CURLOPT_POST, true );
    curl_setopt($ch, CURLOPT_POSTFIELDS, $request);
    curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
    curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_NTLM);
    curl_setopt($ch, CURLOPT_USERPWD, $this->user.':'.$this->password);
    $response = curl_exec($ch);

    return $response;
  }

  function __getLastRequestHeaders() {
    return implode("\n", $this->__last_request_headers)."\n";
  }
}

Additionally you will have to implement the NTLMStreamWrapper as posted in the example above. Could you help me in implementing this functionality?

BTW. does the EWS Example not use NTLM Authentication?

@mikaelcom
Copy link
Member

It's absolutly correct. The implementation is very easy. You will just need the 3 parameters --ntlm-domain --ntlm-login and --ntlm-password

What would be the usage of the --ntlm-domain parameter ?

Could you help me in implementing this functionality?

For your future usage of the generated package? Or the implementation of the SoapClient that would be used by the generator to access the WSDL?

does the EWS Example not use NTLM Authentication?

The PackageEws365 does not need NTLM authentication to consume the Office 365 Web Service as demonstrated by the sample. It would probably work with a non Office 365 Web Service but I really don't know.

As I said, it's hard for me to be sure of what has to be done if I don't have the availability to do my own tests with a NTLM authentication. I understand your position but if we could communicate privately at [email protected], we could agreee on a process in order to allow me to do my reseaerch and tests. Let me know what could be done, Thanks,

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants