AnsweredAssumed Answered

generateToken succeeds, but token not being accepted when in use in Esri-Leaflet

Question asked by SimonWebster.QFES on Jun 24, 2019
Latest reply on Jul 11, 2020 by SimonWebster.QFES

This question probably doesn't belong to one single developer group, but the Esri-Leaflet implementation is the ultimate end goal, and probably has developers most familiar with the stack - so here goes:

 

I have a standalone ArcGIS server situation, and am wanting to access secure feature services. My site runs on PHP 7.3, and has access to cURL. Ideally I'd like to collect the token using credentials stored in PHP, using cURL, and then deliver that token to Esri-Leaflet when I do an addtomap, thus keeping the credentials secure. 

 

The error that I'm facing at the response to the request is the rather generic:

{"error":{"code":498,"message":"Invalid Token","details":[]}}

 

Temporarily there is a url here:

http://52.65.144.150/esri-js-demo-page/

 

So, what have I done so far? Lets use a secured esri demo service to illustrate, noting that I've left in commented out sections where I've either:

  • Tried to set the referer manually so that cURL is using the same referer as the referer being passed out from the site (hopefully). This included the page calling the map, as seen by lookign at the requests referer being passing in chrome, and also by ensuring that the referer being dumped out by php matched that which chrome was sending. Overall I don't want to use this approach as I'd like to have multiple pages use this bit of php.
  • Tried to use the visitors IP addresses instead. This generated a token but resulted in the same invalid token issue. My organisation can force requests out from different endpoints too, so it's a possible point of instability.
  • Tried to set the referer using other PHP methods such as $_SERVER['HTTP_REFERER'];
  • You can also see my regex for parsing the tokens - this just strips the rest of the response so that all I'm left with is the token string. {".,}. I'm thus not passing an expiry back to the server during the layer request - I cannot see in any documentation that it's required.

 

 

  <?php     

     //Check to see if the request came from the proper application

          //The url to the token endpoint of the sever containing the secure service
          $url = "https://sampleserver6.arcgisonline.com/arcgis/tokens/";
          
         //What is the actual referer - dump it into the page for debugging purposes
          echo $referer = $_SERVER['HTTP_REFERER'];
        
         //The fields included in the request
          $fields = array(
               'request' => 'getToken',
               'username' => 'user1',
               'password' => 'user1',
               'expiration' => 120,
               'clientid' => 'ref.' . $_SERVER['HTTP_REFERER'],
               //'clientid' => 'ref.' . $_SERVER['HTTP_REFERER'],
               //'clientid' => 'ip.' . $_SERVER['HTTP_CLIENT_IP'],
               //'clientid' => 'ip',
               //'ip' => $_SERVER['REMOTE_ADDR'],
               'f' => 'json'
          );
          $fields_string = "";
          foreach($fields as $key=>$value) {
               $fields_string .= $key.'='.$value.'&';
          }
          //Instantiate Curl
          $ch = curl_init($url);
          curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
          curl_setopt($ch,CURLOPT_POST,count($fields));
          curl_setopt($ch, CURLOPT_POSTFIELDS, $fields_string);
          curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
         //curl_setopt($ch, CURLOPT_REFERER, $referer);
          $result = curl_exec($ch);
          
          //If Curl was not instantiated successfully
          if (!curl_exec($ch)) {
               echo 'An error has occurred: ' . curl_error($ch);
          }
          //Otherwise return the result
          else {
               preg_match('/:.*?,/', $result, $token);
               $token = str_replace(':', "", $token);
               $token = str_replace('.",', '"', $token);
               //print_r($token);
               echo '<script type="text/javascript">';
               echo 'var val = '.$token[0];
               echo '</script>';
               //echo $result;
          }
          //Close Curl
          curl_close($ch);
  }
}

 

Now, reload the page that is doing the calling, see that the token is brought in via javascript successfully:

<script type="text/javascript">var val = "9VOz2HXe_mfOXJSVSFr4cgNL-5k6fIMfqTOYytKEefs"</script>

 

Request the service layer:

var pedestrianDistricts2 = L.esri.featureLayer({
      url: 'https://sampleserver6.arcgisonline.com/arcgis/rest/services/Wildfire_secure_ac/FeatureServer/2',
token: val
    }).addTo(map);

 

The request from the network tab of Chrome looks like:

https://sampleserver6.arcgisonline.com/arcgis/rest/services/Wildfire_secure/FeatureServer/?token=9VOz2HXe_mfOXJSVSFr4cgNL-5k6fIMfqTOYytKEefs&f=json

The response looks like:

{"error":{"code":498,"message":"Invalid Token","details":[]}}

 

 

 

As an aside I tried this morning to hard code the credentials into a html page as per one of the examples - I was able to get around this error. Since this will be a production system I cannot take this approach. Then I had a different issue altogether, but that's another matter. 

 

I cannot help but think that the referer is causing me grief, but I'm just not sure how to get around the issue.

 

Any bright ideas are appreciated!

Outcomes