Why curls fails to verify google access token whereas browser succeeds?

落花浮王杯 提交于 2019-12-25 02:07:12

问题


with this simple code I manage to get Google's access tokens. See the code:

public function authenticate($code = null) {
  if (!$code) {
     if ($this->log)
        error_log(__CLASS__ . '::authenticate() error: $code is null.');
     return false;
  }
  $client_id = $this->token->get('client_id');
  $client_secret  = $this->token->get('client_secret');
  $redirect_uri = $this->token->get('redirect_uri');
  $url = $this->token->get('token_endpoint');
  $curlPost = 'client_id=' . $client_id . '&client_secret=' . $client_secret . '&redirect_uri=' . $redirect_uri . '&code='. $code . '&grant_type=authorization_code';
  $ch = curl_init();
  curl_setopt($ch, CURLOPT_URL, $url);
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
  curl_setopt($ch, CURLOPT_POST, 1);
  curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
  curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
  curl_setopt($ch, CURLOPT_POSTFIELDS, $curlPost);
  $buffer = curl_exec($ch);
  $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
  curl_close($ch);
  $data = \json_decode($buffer, true);
  if ($http_code != 200) {
     $log = __CLASS__ . '::authenticate() error: http code not 200. Responded: '.print_r($data, true);
     $return = false;
  } else {
     $this->auth = $data;
     $return = true;
     $log = __CLASS__ . '::authenticate() returns '.$return.' and sets this->auth='.print_r($data, true);
  }
  if ($this->log)
     error_log($log);
  return $return;
}

you can see my project there with a test file.

My question is about the verify() function. When I want to verify Google's access token by typing in the browser sth like https://www.googleapis.com/oauth2/v2/tokeninfo?access_token=.... I get immediately a response from Google but when I try the following function with cURL it fails miserably:

public function verify($access_token = null) {
  if (!$access_token) {
     if ($this->log)
        error_log(__CLASS__ . '::verify() error: $access_token is null.');
     return false;
  }
  $url = $this->token->get('verify_endpoint');
  $curlPost = 'access_token='. $access_token;
  //$curlPost = \http_build_query(array('access_token' => $access_token));
  //$curlPost = array('access_token' => $access_token);
  $ch = curl_init();
  curl_setopt($ch, CURLOPT_URL, $url.'?'.$curlPost);
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
  curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
  curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
  //curl_setopt($ch, CURLOPT_VERBOSE, true);
  $buffer = curl_exec($ch);
  $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
  curl_close($ch);
  $data = \json_decode($buffer, true);
  if ($http_code != 200) {
     $log = __CLASS__ . '::verify() error: http code not 200. Responded: '.print_r($data, true);
     $return = false;
  } else {
     $this->verify = $data;
     $log = __CLASS__ . '::verify() sets this->verify='.print_r($data, true);
     $return = true;
  }
  if ($this->log)
     error_log($log);
  return $return;
}

Has this sth to do with cURL? Any answer is welcomed.

Just to clarify: browser request https://www.googleapis.com/oauth2/v2/tokeninfo?access_token=... or with ?id_token=... always succeeds BUT not cURL with the proper tokens in the query part of course.


回答1:


From your source code here

$this->set('verify_endpoint', 'https://www.googleapis.com/oauth2/v2/tokeninfo');

is calling googles token info end point documentation is used for validating an id token you appear to be passing it an access token. This is not going to work.

TBH i dont understand why you would bother validating an access token. The best way to test if an access token is working is to make the call to the API in question if it doesnt work you will get an error back. Why would you want to make a call to test if it works then use it if it does work your doubling your requests.




回答2:


Problems solved!

After a 2 month searching at last there is an update version of my project wirh cUrl problems solved immediately after started to investigate errors sent by the curl environment.

The browser success ringed a bell that probably there was a DNS issue as these threads repeatedly showcase this:

  1. https://curl.haxx.se/mail/curlphp-2016-10/0000.html
  2. https://forums.rancher.com/t/dns-caching-issues/1566/8 @vincent
  3. https://github.com/GoogleCloudPlatform/google-cloud-php/issues/405
  4. https://github.com/google/google-api-php-client/issues/1184

This discussion from @sanmai about CURLOPT_RESOLVE actually made it working! Also see php manual; The same is proposed here by Luc van Donkersgoed and there by John Hart.

The tricky parts of response headers on GET requests that contain Google's response are discussed here and in other places.

Curl certificates are downloaded from there. A discussion for certificates is there.

A discussion for debugging cUrl here and there.

For a discussion of Expect header and it's implications you can read this and that.

Now cUrl is lightning fast when it connects to google. See my project.

My deepest gratitude to all the users who patiently and kindly support the community. You guys are awesome! many thanks!



来源:https://stackoverflow.com/questions/47940730/why-curls-fails-to-verify-google-access-token-whereas-browser-succeeds

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!