0

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.

centurian
  • 1,168
  • 13
  • 25
  • I can't help with an answer. However in the first code block this: `$curlPost = 'client_id=' . $client_id . '&client_secret=' ......` is bad because you're not encoding URI string. Just let `$curlPost` an associative array an pass it `curl_setopt($ch, CURLOPT_POSTFIELDS, $curlPost);` letting curl do the URI encoding job – Paolo Dec 22 '17 at 11:35
  • $url = $this->token->get('verify_endpoint'); <-- what is that? The only way to verify an access token is to make an api call. Which api call are you making and what is the error you are getting? – Linda Lawton - DaImTo Dec 22 '17 at 12:16
  • @DaImTo Yes, the code uses some helper classes as in github project (https://github.com/centurianii/googleclient); that's the actual url for verification stored in class GoogleToken – centurian Dec 22 '17 at 12:25
  • @Paolo I can authenticate, I can verify with my browser BUT curl still fails on verification with message: Array ( [error_description] => Unsupported content with type: multipart/form-data; boundary=------------------------4771c015d2208399 ) – centurian Dec 22 '17 at 12:35
  • I suspect the way I use curl in verify() is not a clear GET request; at the end I shouldn't verify at all but still I wonder why curl fails? – centurian Dec 22 '17 at 12:50

2 Answers2

0

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.

Linda Lawton - DaImTo
  • 106,405
  • 32
  • 180
  • 449
  • Ok, I have the access token, I put in my browser: `https://www.googleapis.com/oauth2/v2/tokeninfo?access_token=ya29.Gl...` and I can see immediate response! My question is what is going with curl equivalent. You suggest not to do this step? – centurian Dec 22 '17 at 12:40
  • I pass `id_token` from browser: succeeds, from curl: fails! I suspect curl does not make a clear GET request here... – centurian Dec 22 '17 at 12:47
  • Probably because what you are giving curl isnt an id token its an access token. Passing an Id_token via a http get will work. Why are you bothering to test this exactly? – Linda Lawton - DaImTo Dec 22 '17 at 12:49
  • $curlPost = 'token_id='. $token_id; <--- try that. Remember an access token is not a token id – Linda Lawton - DaImTo Dec 22 '17 at 12:50
  • I log google's response so i can see `Array ( [access_token] => ya29.G...O0 [expires_in] => 3600 [id_token] => eyJhb...Obg [refresh_token] => 1/wLy...9i [token_type] => Bearer )` – centurian Dec 22 '17 at 12:54
  • then send id token – Linda Lawton - DaImTo Dec 22 '17 at 12:55
0

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!

centurian
  • 1,168
  • 13
  • 25