Google-api-php-client: Bug when authenticate users in backend server

Created on 25 Jul 2017  路  10Comments  路  Source: googleapis/google-api-php-client

Hello,
I've put this same post in stackoverflow, but I think we will be better here, due is likely a bug.

I have the next code, got directly from google reference (https://developers.google.com/identity/sign-in/web/backend-auth)

public function verifyFromAndroid($idToken=null) {
        if(empty($idToken)) {
            $idToken = self::SAMPLE_ID_TOKEN;
        }
        $client = new Google_Client(['client_id' => self::CLIENT_ID]);
        $payload = $client->verifyIdToken($idToken);
        if ($payload) {
            print_r($payload);
          $userid = $payload['sub'];
          // If request specified a G Suite domain:
          //$domain = $payload['hd'];
        } else {
            var_dump($payload);
          $this->lastError = "Invalid ID token";
          return false;
        }
    }

But this method always returns false, even using a valid id token that is created and working using the oauthplayground online tool. https://developers.google.com/oauthplayground/

The next code works fine, using directly the GoogleAccessToken_Verify class.

try {
            $verify = new Google_AccessToken_Verify();
            $result = $verify->verifyIdToken($this->idToken);
            if($result) {

                print_r($result);
                $friendlyData = $this->translateData($result, true);
                if(!$friendlyData) {
                    return false;
                }
                return $friendlyData;
            }
            else {
                $this->lastError = "Invalid token verification, no error code";
                return false;
            }
        }
        catch(UnexpectedValueException $ex) {
            $this->lastError = "UnVaEx (Code {$ex->getCode()}): {$ex->getMessage()}";
            return false;
        }

Can someone tell me why the official Google code doesn't work and yes my own code using the official Google-api-php-client sdk?

p2 bug

Most helpful comment

@MarsVard If you take a look here:
https://github.com/google/google-api-php-client/blob/d669e0f3b92da94d5b4ed960d462dd3b0de920ea/src/Google/AccessToken/Verify.php#L106-L110

It isn't sending the client_id anywhere. It is just comparing it to "aud" property of idToken. So you can do like:

$idToken = 'EAA....etc...';
$iosToken = '[email protected]';
$androidToken = '[email protected]';

$client = new \Google_Client();
$data = $client->verifyIdToken($idToken);

return $data && in_array($data['aud'], [ $iosToken, $androidToken ]);

All 10 comments

I have same issue, i follow google reference but server side verification fail every time.
HTML + Javascript

<script src="https://apis.google.com/js/platform.js" async defer></script>
<script>
    function onSignIn(googleUser) {
        var profile = googleUser.getBasicProfile();
        console.log('ID: ' + profile.getId()); 
        console.log('Name: ' + profile.getName());
        console.log('Image URL: ' + profile.getImageUrl());
        console.log('Email: ' + profile.getEmail());
                // ok here, everything is displayed

        var id_token = googleUser.getAuthResponse().id_token;

        var xhr = new XMLHttpRequest();
        xhr.open('POST', "{{URL("sessions/sso/google");}}");
        xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
        xhr.onload = function() {
          console.log('Signed in as: ' + xhr.responseText);
        };
        xhr.send('idtoken=' + id_token);

      }
</script>
<meta name="google-signin-client_id" content="{{CLIENT_ID}}.apps.googleusercontent.com">
<div class="g-signin2" data-scope="profile email" data-width="298" data-onsuccess="onSignIn"></div>

PHP

$id_token = input::post('idtoken');
$client = new Google_Client(['client_id' => self::client_id]);
$payload = $client->verifyIdToken($id_token);
var_dump($payload);//bool(false)

@mvcmaker if you drop the client id argument from the Google_Client-constructor, does it work then? I had this same problem but the reason was I was using wrong client id..

@ernofi does your verifyToken call work without client_id?

@MarsVard yes it does.

@ernofi @mvcmaker it's working for us without setting a client_id in php, can somebody clarify why the docs are stating otherwise?

We are using a different client_id for android and another one for iOS because we generated a different id for each platform.

And on the web-server we don't set any id while calling verifyToken... this works, while it shouldn't in our opinion.... any ideas?

Edit

Ok, we figured it out.

  1. your clients should use their own client_ids (android and iOS seperately).
  2. your server knows these client_ids and uses these to verify the tokens, depending on the client that sends it.

So if your server gets a token from android, it should use the android client_id, if it gets a token from iOS it should use the iOS client_id to verify the token.

that's it.

note: on iOS you should use an iOS auth client, while on android you should use a web auth client, the android auth client keeps throwing and "Api exception 10"

@MarsVard If you take a look here:
https://github.com/google/google-api-php-client/blob/d669e0f3b92da94d5b4ed960d462dd3b0de920ea/src/Google/AccessToken/Verify.php#L106-L110

It isn't sending the client_id anywhere. It is just comparing it to "aud" property of idToken. So you can do like:

$idToken = 'EAA....etc...';
$iosToken = '[email protected]';
$androidToken = '[email protected]';

$client = new \Google_Client();
$data = $client->verifyIdToken($idToken);

return $data && in_array($data['aud'], [ $iosToken, $androidToken ]);

@ernofi I know, but using the android client_id in android keeps throwing an "ApiException: 10", I'm 100% sure my key sha1 and package name are correct on the developer console

Any idea how to solve this problem?
I have exactly same situation. Except the verification work on local machine and fail on production server.
Local machine running MacOS with LibreSSL 2.2.7
Production server running Ubuntu 16.04 with OpenSSL OpenSSL 1.1.0h 27 Mar 2018

At this moment, this method work for me on both local and production:

$verify = new Google_AccessToken_Verify();
 return $verify->verifyIdToken($token);

@oxycoder You might be better served by opening a new issue and explaining you problem in greater detail. Include a code snippet of broken code and what you expect its behavior should be. It also helps to know what API you are trying to access.

This thread seems resolved. If anyone is still having problems let's address them in a new issue.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

ghost picture ghost  路  4Comments

cmcfadden picture cmcfadden  路  5Comments

ysaurabh33 picture ysaurabh33  路  3Comments

slaFFik picture slaFFik  路  5Comments

armetiz picture armetiz  路  4Comments