Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get additional scope information from Google PHP API payload?

I'm struggling with getting additional scope information from the Google PHP API. I'm using it in conjunction with JavaScript to get an access token (not sure if this is the correct way, but it works for me)

I have a Google sign up button on my page that's connected to the following function. Basically, it gets a response token to send to my PHP server trough AJAX.

gapi.load('auth2', function() {
    // Retrieve the singleton for the GoogleAuth library and set up the client.
    auth2 = gapi.auth2.init({
        client_id: 'XXXX',
        cookie_policy: 'single_host_origin',
        // Requesting additional scopes
        scope: 'https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/userinfo.profile https://www.googleapis.com/auth/plus.login'
    });

    auth2.attachClickHandler(document.getElementById('google-login-signup'), {},
        function(googleUser) {

            if ( auth2.isSignedIn.get() ) {

                var data = {
                    'action': 'social_google_login',
                    '_nonce': $('#google-login-signup').attr('data-nonce'),
                    'redirect_to': $('#google-login-signup').attr('data-redirect-to'),
                    'token': googleUser.getAuthResponse().id_token
                }

                $.ajax({
                    url: ajax_url,
                    type: 'POST',
                    data: data,
                    success: function(response) {
                        console.log(response);

                        if ( response.success === true ) {
                            window.location.href = response.data.redirect;                  
                        }
                    }
                });

            }

        }, function(error) {

            console.log(error);

        }
    );
});

Then on my server, the token is retrieved and fed through the following function, which checks if the token is valid and returns the info:

public function connect() {
    $client = new Google_Client();

    $credentials = json_decode('XXXX', true);       
    $client->setAuthConfig($credentials);       

    $payload = $client->verifyIdToken($_POST['token']);

    if ( !$payload ) {
        return new WP_Error('invalid_payload', 'The payload was invalid.');         
    }

    return $payload;        
}

This all works fine, except that it doesn't include the information from the additional scopes I requested in the JavaScript function. How can I get this additional scope information such as the birthday and sex?

Just for reference, this is what the $payload variable returns:

at_hash: "XXXX"
aud: "XXXX.apps.googleusercontent.com"
azp: "XXXX.apps.googleusercontent.com"
email: "[email protected]"
email_verified: true
exp: 1520189629
family_name: "XXXX"
given_name: "XXXX"
iat: XXXX
iss: "accounts.google.com"
jti: "XXXX"
locale: "en"
name: "XXXX XXXX"
picture: "XXXX"
sub: "XXXX"
like image 918
Swen Avatar asked Mar 04 '18 18:03

Swen


People also ask

How do I add a scope to Google API console?

Go to the Google API Console OAuth consent screen page. Add required information like a product name and support email address. Click Add Scope. On the dialog that appears, select the scopes your project uses.

What is Google OAuth scope?

About OAuth and OAuth scopes You use Open Authorization (OAuth) to grant permission to third-party services to access a user's account information without exposing the user's password. With OAuth scopes, you can allow apps to request permission to certain user data. Your users must then permit access to the app.


1 Answers

I managed to figure it out. The main problem was I was trying to access data through the id_token, but what I needed to do was use an access_token and pass it through other Google APIs.

In case anyone stumbles upon this, here is my new and improved code, which also fixes some issues I had unrelated to this question.

JavaScript

$('#google-login-signup').on('click', function(e) {
    e.preventDefault();

    gapi.load('auth2', function() {

        var scopes = [
            'https://www.googleapis.com/auth/userinfo.email',
            'https://www.googleapis.com/auth/userinfo.profile',
            'https://www.googleapis.com/auth/plus.login'
        ];

        // Use gapi.auth2.authorize instead of gapi.auth2.init.
        // This is because I only need the data from Google once.
        gapi.auth2.authorize({
            'client_id': 'XXXX.apps.googleusercontent.com',
            'cookie_policy': 'single_host_origin',
            'fetch_basic_profile': false,
            'ux_mode': 'popup',
            'scope': scopes.join(' '),
            'prompt': 'select_account'
        },
        function(googleResponse) {

            if ( googleResponse.error ) {
                return;
            }

            var data = {
                'action': 'social_google_login',
                '_nonce': $('#google-login-signup').attr('data-nonce'),
                'redirect_to': $('#google-login-signup').attr('data-redirect-to'),

                // Instead of id_token, send the access_token.
                // This is needed for accessing the scope info from other APIs.
                'access_token': googleResponse.access_token
            }

            $.ajax({
                url: ajax_url,
                type: 'POST',
                data: data,
                success: function(response) {
                    if ( response.success === true ) {
                        window.location.href = response.data.redirect;                              
                    }
                }
            });         
        });             
    });
});

PHP

public function connect() {
    $client = new Google_Client();

    $credentials = json_decode('XXXX', true);

    $client->setAuthConfig($credentials);

    // Set Access Token
    $client->setAccessToken($_POST['access_token']);

    // Connect to Oauth2 API after providing access_token to client
    $oauth2 = new Google_Service_Oauth2($client);

    if ( !$oauth2 ) {
        return new WP_Error('invalid_access_token', 'The access_token was invalid.');   
    }

    // Contains basic user info
    $google_user = $this->get_user($oauth2->userinfo->get());

    // To get the plus.login scope we need to setup a Google_Service_Plus
    $google_plus_service = new Google_Service_Plus($client);

    // Contains Google+ profile info
    $profile = $google_plus_service->people->get('me');

}

That's it! it was basically an issue of not knowing that I needed to access a different Google_Service to get the additional scope information.

like image 149
Swen Avatar answered Sep 21 '22 06:09

Swen