Google Identity Service - How Obtain Profile / Email Information From Authenticated user
Asked Answered
T

2

5

I'm porting over some existing js code authenticating with the google cloud platform (as they are migrating to a new set of libraries).

(migration guide: https://developers.google.com/identity/oauth2/web/guides/migration-to-gis)

I'm struggling with getting a hold of the player's profile (to obtain their email).

The old approach would be along the lines of this (but as it says, it is now deprecated - I've been reading the new docs but it mostly surrounds getting authorized/authenticate and not the follow on from that): https://developers.google.com/identity/sign-in/web/people

e.g.

var profile = auth2.currentUser.get().getBasicProfile();
var email = profile.getEmail();

In my new code I've have the access token, via the new approach:

    client_id: vm.clientId,
    scope: SCOPE,
    callback: (tokenResponse) => {
        if (tokenResponse && tokenResponse.access_token) {
            access_token = tokenResponse.access_token;

            // HERE??? HOW DO I GET THE PROFILE?

        }
    }
})

(largely taken from https://developers.google.com/identity/oauth2/web/guides/use-token-model)

I've seen this mentioned elsewhere but it doesn't work in my situation at least:

gapi.client.oauth2.userinfo.get().execute(function (resp) {
   console.log(resp);
})

(How to get profile information from Google Identity Services?)

I've read via the migration guide: 'Instead, use direct references to credential sub-fields in the new JWT CredentialResponse object to work with user profile data.' but don't know how to get this Credentialresponse? (https://developers.google.com/identity/gsi/web/guides/migration#token_response)


Tooley answered 30/1, 2023 at 10:42 Comment(4)
where did you get that code? can i see a link to the docsGwenora
Thanks - I've edited the original post to include some links. The code is largely taken from developers.google.com/identity/oauth2/web/guides/…Tooley
Take the access token and use it to either request profile info from the userinfo endpoint or the people api assuming that you have requested the profile scopeGwenora
Thank you - I think I might have it... just testing and will post a more detailed summary / sample code.Tooley
S
7

You can follow these steps that I had to undertake to achieve the entire flow using Javascript.

First create a button that will hold the HTML element:

<button id="btnGoogleSignIn" style="border:none;background: none;"> </button>

You can then use the below script and associated functions in which I am getting the JWT token from Google and then decoding it to get the required information out like email address etc. Note that I am calling the onSignInGSI as callback on the button initialization.

<script>  
    function decodeJwtResponseFromGoogleAPI(token) {
            let base64Url = token.split('.')[1]
            let base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/');
            let jsonPayload = 
           decodeURIComponent(atob(base64).split('').map(function (c) {
                return '%' + ('00' + 
           c.charCodeAt(0).toString(16)).slice(-2);
            }).join(''));
            return JSON.parse(jsonPayload)
        }

    function onSignInGSI(response) {
        //console.log(response)
        responsePayload = decodeJwtResponseFromGoogleAPI(response.credential);
        console.log("ID: " + responsePayload.sub);
        console.log('Full Name: ' + responsePayload.name);
        console.log('Given Name: ' + responsePayload.given_name);
        console.log('Family Name: ' + responsePayload.family_name);
        console.log("Image URL: " + responsePayload.picture);
        console.log("Email: " + responsePayload.email);
    }

    window.onload = function () {

        google.accounts.id.initialize({
            client_id: client_id,
            context: 'signin',
            callback: onSignInGSI
        });

        google.accounts.id.prompt();
        
        google.accounts.id.renderButton(document.getElementById("btnGoogleSignIn"), 
        {
            type: "standard",
            text: "signin_with",
            logo_alignment: "left",
            width: 375
        });
    };
</script>
<script src="https://accounts.google.com/gsi/client" async defer></script>
Symbiosis answered 8/2, 2023 at 8:44 Comment(2)
Hi Rahul, on your other similar answer [https://mcmap.net/q/2030248/-using-google-identity-service-to-create-a-sign-up-button-but-nothing-is-displayed-in-popup-window], you've added a parameter for prompt method later on. Can you explain "Why is the prompt not displayed in certain situations", and "what is skipped moment" please?Nolanolan
@CevdetHamarat The skipped moment occurs when the One Tap prompt is closed by an auto cancel, a manual cancel, or when Google fails to issue a credential, such as when the selected session has signed out of Google. Now in such cases we manually invalidate the g_state cookie. But more most reasons, the prompt is not displayed because you have not added the domain to the Authorised Javascript Origins. You will a get GSI Logger error on the console for such cases.Symbiosis
T
3

Adding a function like this works in my situation:

function getUserProfileData(accessToken) {
    let promise = new Promise(function(resolve, reject) {
        let request = new XMLHttpRequest();
        const url = `https://www.googleapis.com/oauth2/v3/userinfo`;
        request.addEventListener("loadend", function() {
            const response = JSON.parse(this.responseText);
            if (this.status === 200) {
                resolve(response);
            } else {
                reject(this, response);
            }
        });
        request.open("GET", url, true);
        request.setRequestHeader('Authorization', `Bearer ${accessToken}`);
        request.send();
    });

    promise.then(function(response) {
        var email = response.email;
    }, function(errorMessage) {
        // TODO: print error
    });
} 

This returns a json that contains the following properties:

  • email
  • email_verified
  • family_name
  • given_name
  • hd
  • name
  • picture
  • sub
Tooley answered 30/1, 2023 at 12:38 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.