Search code examples
phpgoogle-plusgoogle-oauthgoogle-php-sdk

"Login with Google" in PHP - Google+ API shutdown migration - how to migrate away from plus.people.get?


I got a warning email from Google reminding me of Google+'s EOL which is supposed to break my current "Login with Google", but I am unsure what exactly should I change.

enter image description here

Let me show you my (simplified) login code:

google-login.php

new class {
    public function __construct() {
        $state = mt_rand();

        $client = new Google_Client();
        $client->setApplicationName(Config::Google['app_name']);
        $client->setClientId(Config::Google['id']);
        $client->setClientSecret(Config::Google['secret']);
        $client->setRedirectUri(sprintf('https://%s/members/google-callback.php', $_SERVER['HTTP_HOST']));
        $client->setScopes(['profile', 'email']);
        $client->setState($state);

        $_SESSION['state'] = $state;
        $url = $client->createAuthUrl(); // $url = https://accounts.google.com/o/oauth2/auth?response_type=code&access_type=online&client_id=CLIENT_ID.apps.googleusercontent.com&redirect_uri=https%3A%2F%2Fread2me.online%2Fmembers%2Fgoogle-callback.php&state=1588245f23f2a&scope=profile%20email&approval_prompt=auto

        header ("location: $url");
    }
};

google-callback.php

new class {
    private $newUser = false;

    public function __construct() {
        if (!isset($_GET['state']) || $_GET['state'] != $_SESSION['state'])
            die('State mismatch.');

        $client = new Google_Client();
        $client->setApplicationName(Config::Google['app_name']);
        $client->setClientId(Config::Google['id']);
        $client->setClientSecret(Config::Google['secret']);
        $client->setRedirectUri(sprintf('https://%s/members/google-callback.php', $_SERVER['HTTP_HOST']));
        $client->setScopes(['profile', 'email']);

        $plus = new Google_Service_Plus($client);

        if (isset($_GET['code'])) {
            $client->fetchAccessTokenWithAuthCode($_GET['code']);
            $_SESSION['token'] = $client->getAccessToken();
        }

        if (isset($_SESSION['token'])) {
            $client->setAccessToken($_SESSION['token']);
        }

        if (!$client->getAccessToken() || $client->isAccessTokenExpired()) {
            $state = mt_rand();
            $client->setState($state);
            $_SESSION['state'] = $state;
            $url = $client->createAuthUrl();

            header ("location: $url");
        }

        try {
            $me = $plus->people->get('me');
        } catch (Google_Exception $e) {
            \Rollbar::report_message($e->getMessage());
            print_r($e->getMessage());

            return;
        }

        $accessToken = $client->getAccessToken()['access_token'];
        $email = $me->getEmails()[0]->getValue();
        $name = $me->getDisplayName();
        $avatar = $me->getImage()->getUrl();
        $id = $me->getId();

        if ($this->isEmailInSystem($email) === false) {
            $this->newUser = true;
            $this->addUser($email, $name, 'google', $accessToken, $id, $avatar);
        }

        header ("location: " . '/');
    }
};

Now, I'm going through at what seems to be the up-to-date Sign In guide for PHP, but I am not sure what to change - any ideas?

Thanks


Solution

  • The best migration is to move from the Plus API to the People API, which provides access to the user's profile in a similar (tho not quite identical) way.

    You would replace the creation of the $plus object with a new Goolge_Service_PeopleService object. Something like

    $people = new Google_Service_PeopleService( $client );
    

    Getting the profile is more involved since you need to specify which fields from the profile you want to get. But you might do it something like

    $profile = $people->people->get(
      'people/me', 
      array('personFields' => 'names,emailAddresses,photos')
    );
    

    The first parameter needs to be "people/me" to specify that you're requesting the authorized user's profile.

    The second is an array of query parameters. You need to specify the "personFields" that you want from the list of what is available (scroll down on this page till you see the description of the available fields) and specify this as a comma separated list in a string. In my example above, I illustrate getting the name, email addresses, and photos. But consult the list and experiment.

    The exact fields you get from the result in $profile will be different than those you got from $plus, but they should match the fields you requested. Check the values and exactly how they're structured.