使用npm包googleapis如何在验证后获取用户的电子邮件地址?

时间:2016-04-13 00:39:51

标签: node.js authentication oauth-2.0 google-api-nodejs-client

我正在使用此npm库 - https://www.npmjs.com/package/googleapis,并且我使用以下Express路线作为/user/

/* Redirect to the google login page */
  router.get('/login', function (req, res) {
    res.redirect(auth.generateUrl());
  });

  /* The callback from the google OAuth API call */
  router.get('/callback', function (req, res) {
    auth.authenticate(req.query.code);

    res.send();
  });

auth就是这个模块:

var oAuth2 = require('googleapis').auth.OAuth2;

var oauth2Client = new oAuth2([CLIENT_ID], [CLIENT_SECRET], [DOMAIN] + '/user/callback');

module.exports = {
    /**
     * Generate a url to redirect to for authenticating via Google
     *
     * @return {String}
     */
    generateUrl: function () {
        return oauth2Client.generateAuthUrl({
            access_type: 'online', // 'online' (default) or 'offline' (gets refresh_token)
            scope: ['https://www.googleapis.com/auth/userinfo.email'] // If you only need one scope you can pass it as string
        });
    },
    authenticate: function (code) {
        oauth2Client.getToken(code, function (err, tokens) {
            console.log(err);

            // Now tokens contains an access_token and an optional refresh_token. Save them.
            if (!err) {
                console.log(tokens);

                oauth2Client.setCredentials(tokens);
            }
        });
    }
};

上面的身份验证功能基于https://www.npmjs.com/package/googleapis#retrieve-access-token中的示例。

现在,如果我转到/user/login,我会看到谷歌登录页面,然后请求我的许可。我使用了上面的电子邮件范围但我没有在返回的tokens对象中看到我的电子邮件地址。这就是我得到的:

{ access_token: '[72 length string]',
  token_type: 'Bearer',
  id_token: '[884 length string]',
  expiry_date: [integer timestamp] }

这不是如何获取电子邮件地址吗?文档不是很清楚,也没有我在网上找到的示例教程,因为它们主要处理谷歌的特定服务,比如日历。我只对基本身份验证感兴趣。我找不到任何其他可能在文档中获取范围信息的方法。

也是一个小问题,但是当用户登录时,我是否必须在每个请求上调用getToken()

修改

在对库的代码进行了一些挖掘之后,我发现了这个:

this.userinfo = {

    /**
     * oauth2.userinfo.get
     *
     * @desc Get user info
     *
     * @alias oauth2.userinfo.get
     * @memberOf! oauth2(v1)
     *
     * @param  {object=} params - Parameters for request
     * @param  {callback} callback - The callback that handles the response.
     * @return {object} Request object
     */
    get: function(params, callback) {
      var parameters = {
        options: {
          url: 'https://www.googleapis.com/oauth2/v1/userinfo',
          method: 'GET'
        },
        params: params,
        requiredParams: [],
        pathParams: [],
        context: self
      };

      return createAPIRequest(parameters, callback);
    }

这是node_modules/googleapis/apis/oauth2/v1.jsnode_modules/googleapis/apis/oauth2/v1.js。但是,这似乎不是require('googleapis').auth.OAuth2使用的,node_modules/google-auth-library/lib/auth/oauth2client.js。有没有办法访问userinfo.get

进一步修改

我找到了这个教程 - https://www.theodo.fr/blog/2014/06/dont-bother-with-keys-open-your-door-with-google-api/,其中这一部分(靠近页面底部)正是我想要做的:

googleapis.discover('oauth2', 'v1').execute(function(err, client) {
    if (!err) {
        client.oauth2.userinfo.get().withAuthClient(oauth2Client).execute(function(err, results) {
            var email = results.email;

            if ((email.indexOf('theodo.fr') + 'theodo.fr'.length) != email.length) {
                return res.send({
                    status: -1,
                    message: "Google Plus authentication failed (domain mismatch)"
                });
            }

            doorClient.open();

            res.send({
                status: 0,
                message: 'Door opened. Welcome !'
            });
        });
    }
});

不考虑Google API的绝对荒谬冗长,此代码不再有效。 discover不再是一项功能,因此我不知道如何访问包含我需要的v1功能的v2userinfo.get

2 个答案:

答案 0 :(得分:7)

对于我没有的版本,即2.1.6,使其工作的方式是:

RewriteCond %{QUERY_STRING} ^/text(.*)$
RewriteRule http://www.google.com [R=301,L]

我必须查看源代码以找出如何做到这一点,我不能100%确定这是否是最好的方法因为我必须两次提到“v2”。但它对我有用。

答案 1 :(得分:2)

我的解决方案:

public deriveAKey(input, encryptKey, cryptoIV) {

    var ref: TopDivComponent = this;
    console.log('Testing before importKey...');

    window.crypto.subtle.importKey(
        "raw",
        ref.stringToArrayBuffer(encryptKey),
        {
            name: "AES-CTR",
        },
        true,
        ["encrypt"]
    ).then(function (key) {
        console.log('Inside then...');
        var newvar = ref.stringToArrayBuffer(cryptoIV);
        var encrypt = window.crypto.subtle.encrypt(
            {
                name: "AES-CTR",
                counter: newvar,
                length: 128,
            },
            key,
            ref.stringToArrayBuffer(input)
        ).then(function (encrypted) {
            var temp = ref.arrayBufferToString(encrypted);
            console.log('Encrypted First: ' + encrypted);
            console.log('Temp: ' + temp);
            console.log('Key: ' + key);
            let fin_encrypted = btoa(temp);
            // console.log('Encrypted Snc/d: ' + fin_encrypted);
            ref.response(fin_encrypted);
            // console.log('From deriveKey: ' + fin_encrypted);
        });
    });
}