【问题标题】:How to verify the client token and get the email address of the user如何验证客户端令牌并获取用户的电子邮件地址
【发布时间】:2021-07-24 13:33:02
【问题描述】:

我想从 google auth 获得一封有效的电子邮件,并只需单击使用 google 登录按钮注册我的用户,这样我就可以获得一个令牌,包括这样的用户电子邮件:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta name="google-signin-client_id" content="203772907695-qd52ou2r1bcsht8f515lh63cpqaateq2.apps.googleusercontent.com">
    <script src="https://apis.google.com/js/platform.js" async defer></script>
    <title>Login</title>
</head>
<body>

    <div class="g-signin2" data-onsuccess="onSignIn"></div>

    <script>
    function onSignIn(googleUser) {

        var id_token = googleUser.getAuthResponse().id_token;
        console.log(id_token);
        var xhr = new XMLHttpRequest();
        xhr.open('POST', '/login');
        xhr.setRequestHeader('Content-Type', 'application/json');
        xhr.onload = function() {
            console.log('Signed in as: ' + xhr.responseText);
            if(xhr.responseText == 'success'){
                signOut();
                location.assign('/profile')
            }
        };
        xhr.send(JSON.stringify({token : id_token}));
      }
    </script>
    
</body>
</html>

上面的代码获取token,然后简单地发送到服务器,对吗?

现在在服务器端,我可以使用console.log(token) 记录我们成功发送的客户端令牌:

// Google Auth
const {OAuth2Client} = require('google-auth-library');
const CLIENT_ID = '203772907695-qd52ou2r1bcsht8f515lh63cpqaateq2.apps.googleusercontent.com'
const client = new OAuth2Client(CLIENT_ID);

app.post('/login', (req,res)=>{
    let token = req.body.token;
    console.log(token); // gets the token successfully
    // then we should verify that this token is valid not one sent by a hacker right?

})

问题是我们如何验证这个token 是有效的,而不是由黑客发送的?

因为正如您所见,黑客可以简单地做我们在客户端所做的事情,然后像我们的令牌一样向我们发送令牌......

我现在的做法是向这个 url 发送带有令牌的 post 请求:

const response = await axios.post(`https://oauth2.googleapis.com/tokeninfo?id_token=${token}`);
const email = response.data.email;

但这并不能验证任何人都可以发送该令牌并获得类似结果...

我想通过验证用户发送的令牌来安全地获取用户电子邮件。

【问题讨论】:

    标签: javascript node.js google-auth-library


    【解决方案1】:

    您可以简单地 read the documentation 解释如何做到这一点。这是他们展示的例子:

    const {OAuth2Client} = require('google-auth-library');
    const client = new OAuth2Client(CLIENT_ID);
    async function verify() {
      const ticket = await client.verifyIdToken({
          idToken: token,
          audience: CLIENT_ID,  // Specify the CLIENT_ID of the app that accesses the backend
          // Or, if multiple clients access the backend:
          //[CLIENT_ID_1, CLIENT_ID_2, CLIENT_ID_3]
      });
      const payload = ticket.getPayload();
      const userid = payload['sub'];
      // If request specified a G Suite domain:
      // const domain = payload['hd'];
    }
    verify().catch(console.error);
    
    【解决方案2】:

    问题是我们如何验证这个令牌是有效的,而不是由黑客发送的?

    黑客无法生成有效令牌,该令牌将从 Google API 获取值。


    Google 使用的是OpenID Connect(OAuth2.0),它非常安全。简而言之,该过程适合您

    1. 点击使用 Google 登录会被重定向到谷歌网站
    2. 您在提供请求的权限后登录那里
    3. 如果登录有效,Google 会将您返回到重定向 URL,前提是它与您在 Google 控制台中创建的应用程序中的 redirect_uri 数组匹配。
    4. 重定向的 uri 有一个代码查询字符串。即,code=*****
    5. 在服务器中,您使用代码和 client_secret(客户端不需要)并code 交换为 access_token/id_token

    令牌是这样生成的,没有其他任意令牌可以使用 Google API 访问任何 Google 资源。它将返回无效令牌错误

    【讨论】:

    • 黑客可以生成一个有效的令牌,该令牌将从 Google API 获取值,因为客户端密钥被放置在客户端上,如您所见......
    • 但是必须交换该代码才能获得token。服务器端。您正在为黑客无法获取的服务器端帖子提供客户端密码
    • client-secret 不在 google-auth-library 中的任何地方使用..
    • 对于客户端流程,攻击是如何可能的,最初用户被重定向到谷歌登录页面。所以黑客,只能使用他的凭据登录。代码是为他的登录 ID 生成的,令牌也是从他的登录 ID 生成的。所以他只能使用他的信息。这就是为什么重定向手动登录到谷歌网站以防止中间人攻击
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-01-16
    • 2014-12-01
    • 1970-01-01
    • 2020-10-31
    • 2016-06-11
    • 2020-09-16
    • 1970-01-01
    相关资源
    最近更新 更多