4 Replies Latest reply on Sep 20, 2017 1:23 PM by eat_k

    PHP cross-domain request to PI WEB API

    eat_k

      Hello,

       

      I am looking for a way to make requests to PI WEB API from PHP in the following environment :

       

      - I have PI WEB API installed and running in domain-A, with Kerberos Authentication enabled

      - I have an apache server in domain-B, on which on php website is running on.

      - Users log into the website using an existing account from domain-B, the server-side php code would use curl to make requests to the PI WEB API in domain-A

       

      After searching around for a white, I could not find a way to make this work. Those are the tests I have done so far :

       

      - if the web server is on the same domain as PI WEB API, the following code works :

       

      function getRequest($url) {
          $ch = curl_init($url);    
          curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);  
          curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);  
          curl_setopt($ch, CURLOPT_GSSAPI_DELEGATION, CURLGSSAPI_DELEGATION_FLAG);  
          curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_GSSNEGOTIATE);  
          curl_setopt($ch, CURLOPT_USERPWD, ":");
          $result = curl_exec($ch);
          $json = json_decode($result, true);
          curl_close($ch);
          return $json;
      } 
      

       

      - using a web browser (IE, Firefox) from a computer in domain-B works. I am also able to view the HTTP requests and responses with Fiddler, but I am not able to do the same in my php code.

       

      I believe I should investigate the Cors (but if I am not wrong, server-side calls are not subject to Cors) and kerberos mechanics but my knowledges are limited to reading documentation and other topics. I have yet to find a way to do this in programming.

       

      The following links are some of the hints I have tried to use thus far :

       

      Developing a PHP application using PI Web API

      Getting started with PI Web API

       

      How to support Pi Web API "Kerberos Authentication" using nodejs/javascript?

      CORS

       

      Now out of idea, I am looking for help in solving this.

       

      You can ask me questions if I forgot any information.

       

      Thanks in advance

          • Re: PHP cross-domain request to PI WEB API
            eat_k

            Hello Marcos,

             

            Thanks for your suggestion, I will try looking into this php client, and read the code he used. I will give you an answer later.

              • Re: PHP cross-domain request to PI WEB API
                Marcos Vainer Loeff

                Hello Kim,

                 

                You are right. The server-side calls against PI Web API are not affected by CORS. Could paste here the exact error that you receive?

                 

                Before troubleshooting this problem in PHP, I would first try to create a simple C# application that will make HTTP requests against PI Web API without hard-coding the username and credentials.  If this works, then we start troubleshooting your PHP code. You might want to use the library from this GItHub repository:

                 

                PIWebApiClient client = new PIWebApiClient("https://yourwebserver/piwebapi", true);
                

                 

                 

                I am supposing that the only authentication method allowed by your PI Web API instance is Kerberos. Am I right?

                1 of 1 people found this helpful
                  • Re: PHP cross-domain request to PI WEB API
                    eat_k

                    Hello Marcos,

                     

                    Our API uses Kerberos to comply with our environment and our security policies. Multiples services/apps do the same in our datacenter so we took the same approach.

                     

                    Going back to the first suggestion, I was able to make something work by :

                    - testing with the API client in your github link.

                    - reproducing the underlying code.

                    I will describe the tests I did.

                     

                    First, about my old code :

                     

                    function getRequest($url) {  
                    $ch = curl_init($url);      
                        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);    
                        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);    
                        curl_setopt($ch, CURLOPT_GSSAPI_DELEGATION, CURLGSSAPI_DELEGATION_FLAG);    
                        curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_GSSNEGOTIATE);    
                        curl_setopt($ch, CURLOPT_USERPWD, ":");  
                    $result = curl_exec($ch);  
                    $json = json_decode($result, true);  
                        curl_close($ch);  
                    return $json;  
                    }   
                    
                    
                    

                     

                    This does not give me php errors. Using Fiddler, the response was only the following (I'm leaving out the urls) :

                     

                    HTTP/1.1 401 Unauthorized
                    Content-Length: 61
                    Content-Type: application/json; charset=utf-8
                    Server: Microsoft-HTTPAPI/2.0
                    WWW-Authenticate: Negotiate
                    

                     

                    I'm guessing my own code was not doing the negotiate process and got stuck before the next step. I am probably missing some configuration in my curl options.

                     

                    Indeed, using the code from the php client :

                     

                    PIWebApiClient client = new PIWebApiClient("myserver", "user", "pass", "KERBEROS", true, false);

                     

                    This worked as i'm getting from Fiddler a chain of responses (also leaving out the urls) :

                     

                    HTTP/1.1 401 Unauthorized
                    Content-Length: 61
                    Content-Type: application/json; charset=utf-8
                    Server: Microsoft-HTTPAPI/2.0
                    WWW-Authenticate: Negotiate
                    
                    HTTP/1.1 401 Unauthorized
                    Content-Length: 0
                    Server: Microsoft-HTTPAPI/2.0
                    WWW-Authenticate: Negotiate A_LONG_TOKEN
                    
                    HTTP/1.1 200 OK
                    Content-Length: 385
                    Content-Type: application/json; charset=utf-8
                    Server: Microsoft-HTTPAPI/2.0
                    

                     

                    I wanted to understand why such difference came out so i went and read the code used. This is a summary of how osimloeff api client does handle kerberos authentication :

                     

                    $curl = curl_init();  
                    curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);  
                    curl_setopt($curl, CURLOPT_HTTPHEADER, array(
                        'Accept: application/json',
                        'Content-Type: application/json')
                    );
                    //curl_setopt($curl, CURLOPT_PROXY, '127.0.0.1:8888');   //this line lets you debug by going through Fiddler
                    curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0);  
                    curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 0);
                    //curl_setopt($curl, CURLOPT_HEADER, 1);                     //include response header for debug
                    curl_setopt($curl, CURLOPT_GSSAPI_DELEGATION, CURLGSSAPI_DELEGATION_FLAG);  
                    curl_setopt($curl, CURLOPT_HTTPAUTH, CURLAUTH_GSSNEGOTIATE);  
                    curl_setopt($curl, CURLOPT_USERPWD, "username:password");
                    curl_setopt($curl, CURLOPT_URL, "https://myserver/piwebapi");
                    $result = curl_exec($curl);  
                    
                    

                     

                    And this works ! I believe curl has to disable verification of peer and host at the same time to work.

                    It also means we are not using SSL in this code which is not recommended for us. We will have to look into it after this. At the moment though, I am already satisfied with the result.

                     

                    Thank you Marcos for taking the time to help me find a solution.