I need to access a RESTful webservice from PHP (only GET for now). The service can only be accessed over HTTPS with a valid client certificate.
I found plenty of basic auth examples for PHP, but not a single one for client-side cert-based HTTP auth. Is there a PHP HTTP client which can also send certificates to the server?
For now I am using an external application (wget), but this is rather slow and hacky.
Certificate-based authentication is not part of HTTP but part of SSL/TLS.
You can use cURL to do such authentication:
$ch = curl_init('https://example.com/');
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, '1');
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, '1');
curl_setopt($ch, CURLOPT_CAINFO, '/path/to/cert/ca.crt');
curl_setopt($ch, CURLOPT_SSLCERT, '/path/to/cert/client-cert.pem');
$response = curl_exec();
curl_close($ch);
See the manual page of curl_setopt for more information on the options.
Related
For many requests I am getting access denied errors when using curl from php, my code is:
$ch = curl_init();
curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2_0);
curl_setopt($ch, CURLOPT_URL, 'https://www.vueling.com/en');
curl_setopt($ch, CURLOPT_TIMEOUT, '2');
curl_setopt($ch, CURLOPT_VERBOSE, 1);
$data = curl_exec($ch);
curl_close($ch);
echo $data;
which returns this:
<H1>Access Denied</H1>
However if I run it directly on the command line:
curl -v https://www.vueling.com/en
I get the full response, my ip is not blocked, im not sure why CLI works but PHP doesnt? Anyone have any ideas?
The CLI version of curl probably sends an user agent that is accepted by this website, but the PHP version of curl may send an user agent that is rejected.
So you have to check that the headers sent by curl are similar in both ways.
I have been using cURL code to access Beanstream for awhile now, and all of a sudden it stopped working as of yesterday. I have determined that this has to do with accessing the HTTPS URL for Beanstream processing, as if I test that same code and just go to the HTTP URL, it works (of course it returns an insecure connection code).
Prior to the below code I was setting VERIFYPEER / VERIFYHOST to FALSE, which was working up until yesterday.
$url = 'https://www.google.com';
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
curl_setopt($ch, CURLOPT_CAINFO, "/xxxx/public_html/_cert/GeoTrustGlobalCA_google.crt");
$getResponse = (curl_exec($ch));
curl_close($ch);
print_r($getResponse);
I have setup the above test code to try and access Google via HTTPS. I had read that a proper connection requires the VERIFYPEER / CAINFO options to be set, which I have done and grabbed the Google .crt and placed it on the web server as well.
I still get a 503 Service Unavailable error back though.
The server is temporarily unable to service your request due to maintenance downtime or capacity problems. Please try again later.
Additionally, a 503 Service Unavailable error was encountered while
trying to use an ErrorDocument to handle the request.
I use curl in PHP to request some https site such as https://github.com, and I use just code like this:
<?php
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "https://github.com/search?q=react");
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$output = curl_exec($ch);
echo $output;
curl_close($ch);
?>
Then, I can get the page.
But, I searched before and found that if requesting a https resource, it needs adding these codes:
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
So why I can request https resource without these two lines of codes to avoid SSL check?
Thanks.
The two Curl options are defined as:
CURLOPT_SSL_VERIFYPEER - verify the peer's SSL certificate
and
CURLOPT_SSL_VERIFYHOST - verify the certificate's name against host
They both default to true in Curl, and shouldn't be disabled unless you've got a good reason. Disabling them is generally only needed if you're sending requests to servers with invalid or self-signed certificates, which is only usually an issue in development. Any publicly-facing site should be presenting a valid certificate, and by disabling these options you're potentially opening yourself up to security issues.
I need to access the Web Service of Navision that is using Navision User + SSL. The connector I am using is based in PHP.
I am able to connect to simple http access and using Window's User. This is the tutorial that helped me achieve this Navision Web Service PHP written by Freddy.
I'm still using it but played around on adding the certificate in the curl/request. Researched and read a lot of article but I still cannot achieve it.
I am now able to access it using the base php connector shared above (link) but when retrieving data I am receiving the details below:
... successfully set certificate verify locations:
* CAfile: /Path/Navision.pem
* SSL connection using TLSv1.0 / AES256-SHA
* Server certificate:
...
* SSL certificate verify result: unable to get local issuer certificate (20), continuing anyway.
* Server auth using NTLM with user 'user'
POST Navision Page URL Name HTTP/1.1
Authorization: NTLM TlRMTVNTUAABAAAABoIIAAAAAAAAAAAAAAAAAAAAAAA=
...
Method: POST
Connection: Keep-Alive
User-Agent: PHP-SOAP-CURL
Content-Type: text/xml; charset=utf-8
SOAPAction: "urn:microsoft-dynamics-schemas/page/pda_item_list:ReadMultiple"
...
< HTTP/1.1 401 Unauthorized ...
I used the certificate by using the makecert.exe. I have these files 2 .cer, a pvk and a .crl.. We used one of the .cer file took the thumbprint to apply it on the navision service instance. Which of the file is the correct one to be used by the php curl connector.
Here is my request php code:
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, USERPWD);
curl_setopt($ch, CURLOPT_VERBOSE, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($ch, CURLOPT_CAINFO, __DIR__ . '/Navision.pem');
Any link that is related would be much appreciated specially if I'll be able to use the web service of Navision using PHP connector by accessing it using Navision User and SSL.
UPDATE
I am now able to use the valid certificate and able to pass through properly.
Still it doesn't now work and returns the the same error above.. Unauthorized 401.
Most likely it is because of my Navision setup or I am just passing the credentials in a wrong way? I am still researching and playing so currently I am still not able to pull the data.
you have two options :
have second service tier which is using Username authentication. This will enable PHP to use Basic Auth. You'll need a cert in this case
the second option is to use the same service tier but generate a Web Service Key for the use what the PHP is using. You can use Basic Auth using the same Username but using the Web Service Key as password
PHP is not a fan of NTLM authentication...
Cheers
As recommended by my DocuSign account manager, I am using Fiddler2 to capture the necessary trace for API certification. I am unable to retrieve the trace from the DocuSign domain and have narrowed it down to the fact that these are cURL calls.
According to Fiddler2, http://fiddler2.com/documentation/Configure-Fiddler/Tasks/ConfigurePHPcURL, the advice is to add the following to code:
curl_setopt($ch, CURLOPT_PROXY, '127.0.0.1:8888');
where $ch = curl_init().
I've also tried
curl_setopt($curl, CURLOPT_PROXY, '127.0.0.1:8888');
Still no dice. I only get traffic from my application site. The following is all of my curl code:
$url = "https://demo.docusign.net/restapi/v2/login_information";
$curl = curl_init($url);
$ch = curl_init();
curl_setopt($curl, CURLOPT_HEADER, false);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_HTTPHEADER, array("X-DocuSign-Authentication: $header"));
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, true);
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 2);
curl_setopt($curl, CURLOPT_CAINFO, getcwd() ."/**the cert info");
curl_setopt($ch, CURLOPT_PROXY, '127.0.0.1:8888');//allows fiddler to see requests
$json_response = curl_exec($curl);
$status = curl_getinfo($curl, CURLINFO_HTTP_CODE);
It's definitely talking to the DocuSign domain as my application is working, I'm just trying to get the trace. Any help is appreciated.
fiddler is client side program, it cannot see server traffic to other servers only traffic between client and server.
Unless your server is running locally (on the same computer that you are running fiddler) using 127.0.0.1 this will not work as 127.0.0.1 is the loopback ip for the computer, in this case the server would be trying to use itself as a proxy (which would be ok if the server computer itself was the one running fiddler). You need to change the ip to the computer running fiddler and make sure the server can access that port.
I was facing the exact same scenario, and I used a protocol analyzer such as Wireshark or TCPDUMP to see HTTP traffic at network level.
Of course the server needs to be running locally. Bellow you can find a screenshot example of traffic capture where you can clearly see the HTTP GET going out.