Google身份验证服务 - 如何从已认证的用户获取个人资料/电子邮件信息

4

我正在移植一些现有的js代码,用于与Google Cloud平台进行身份验证(因为他们正在迁移到一组新的库)。

(迁移指南:https://developers.google.com/identity/oauth2/web/guides/migration-to-gis

我正在努力获取玩家的个人资料(以获取他们的电子邮件)。

旧方法可能是这样的(但正如它所说,现在已经过时了 - 我一直在阅读新文档,但大多数都是关于获取授权/身份验证,而不是其后续步骤): https://developers.google.com/identity/sign-in/web/people

例如:

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

在我的新代码中,我已经通过新方法获得了访问令牌:
    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?

        }
    }
})

(主要参考自https://developers.google.com/identity/oauth2/web/guides/use-token-model

我在其他地方看到过这个提到,但至少在我的情况下它不起作用:

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

(如何从Google身份服务中获取个人资料信息?)

我已经通过迁移指南阅读到:“相反,使用新的JWT CredentialResponse对象中凭据子字段的直接引用来处理用户配置文件数据。”但是不知道如何获取此Credentialresponse? (https://developers.google.com/identity/gsi/web/guides/migration#token_response)



1
你从哪里得到那段代码的?我能看一下文档链接吗? - Linda Lawton - DaImTo
谢谢 - 我已经编辑了原始帖子,包括一些链接。代码大部分来自https://developers.google.com/identity/oauth2/web/guides/use-token-model - Chadz001
获取访问令牌并使用它从userinfo端点或people API请求个人资料信息,前提是您已经请求了个人资料范围。 - Linda Lawton - DaImTo
谢谢 - 我想我可能有了...正在测试,稍后会发布更详细的总结/示例代码。 - Chadz001
2个回答

6
您可以按照以下步骤使用JavaScript实现整个流程:
首先创建一个包含HTML元素的
<button id="btnGoogleSignIn" style="border:none;background: none;"> </button>

您可以使用以下脚本和相关函数,其中我从Google获取JWT令牌,然后对其进行解码以获取所需信息,例如电子邮件地址等。请注意,我在按钮初始化时调用onSignInGSI作为回调函数。
<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>

嗨,Rahul,关于你在另一个类似的答案[stackoverflow.com/a/75382705/4011467]中稍后添加了一个prompt方法的参数。你能解释一下“为什么在某些情况下不显示提示”和“什么是跳过时刻”吗? - Cevdet Hamarat
@CevdetHamarat 当 One Tap 提示框被自动取消、手动取消或 Google 未能发出凭据(例如所选会话已从 Google 登出)时,将发生跳过的情况。在这种情况下,我们会手动使 g_state cookie 失效。但更多的原因是,提示框没有显示,因为您没有将该域添加到“授权 JavaScript 来源”中。对于这种情况,您将在控制台上获得 GSI Logger 错误。 - Rahul Sharma

3

添加这样的函数可以在我的情况下起作用:

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
    });
} 

这将返回一个json,其中包含以下属性:
  • 电子邮件
  • 电子邮件已验证
  • 姓氏
  • 名字
  • 域名
  • 姓名
  • 头像
  • sub

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接