这篇文章写什么?

如何在 Electron.js 中实现谷歌登录。

目标读者

开发者

本文环境:

  • Electron.js 6.1.5
  • Node.js 10还是12不记得了 (没啥影响)

成功后的结果演示:

点击按钮当然是打开网页(如下)提示登录

登录后页面显示这句话。注意这里是 localhost:3000

谷歌网页登录成功! 请关掉此页面. 查看 App 内有没有成功登录. 如果 App 内没看到变化还是看到谷歌登录按钮,请配置代理。 Authentication successful! Please return to the console.

之所以显示这一段话, 是因为代码里写的就是这句

顺带一说,这一句中文,
在其他浏览器里,会有中文乱码问题。这我还没解决。

关掉上面那个网页,回到 App 里可以看到:

这就是登录成功了

via GIPHY

短结论

不想看后文的只参考这个就够了

https://github.com/googleapis/google-auth-library-nodejs

题外话

之所以写这篇文,是因为卡了1-2天。
所以分享下给别人省点时间。

回到正题

下面这一段代码

解释下是:
是监听 3000 端口 .listen(3000
然后打开这个链接 open(authorizeUrl
authorizeUrl 来自这里:

    // Generate the url that will be used for the consent dialog.
    const authorizeUrl = oAuth2Client.generateAuthUrl({
      access_type: 'offline',
      // Scope: https://developers.google.com/identity/protocols/googlescopes
      scope: ['https://www.googleapis.com/auth/cloud-translation',
        'https://www.googleapis.com/auth/userinfo.profile'
      ]
    });

解释另一段:

createServer 创建的 localhost:3000

如果收到请求(谷歌登录成功的 callback url)就会处理

callback url 例子如下:

http://localhost:3000/?code=4%2FuQGk6cmc8fKxr6PHuJE22MRW1DGJVP7JkvYfmRx5CqZ2DzYcQWdA7WzLdMAB6IO85CbwuaZAeB1mkVPLNzzWpSI&scope=profile+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fcloud-translation+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.profile#

处理的这个部分

官方在 createServer 里用 indexOf('oauth2callback')

Github

我改成了 indexOf('code')

我的代码
if (req.url.indexOf('code' > -1) {

这一句意思是:如果 url 里包含 code,就进入 if 分支

简而言之

  1. 先谷歌登录,拿到 code
  1. 拿着 code 去换 credentials

以下是 resolve(oAuth2Client)
把 oAuth2Client.credentials 保存到本地的结果。

不用管 google-user-credentials 这个 key 名字,不重要,是我随便设的。
看内容。
里面最重要的是 access_token 和 refresh_token

之后的所有谷歌 API 请求都用 access_token

如果 access_token 过期了,就拿 refresh_token 去换取新 access_token

举个例子

    const oa2 = new OAuth2Client({
      clientId: [clientId填这里],
      redirectUri: [redirectUri填这里]
    });
    var refresh_token = [拿到之前的 refresh_token]
    oa2.setCredentials({
      refresh_token
    });
    // 刷新
    oa2.refreshAccessToken().then(res => {
      var credentials = res.credentials
      // 我这是在保存刷新后的结果到本地
      window.store.set('google-user-credentials.expiry_date', credentials.expiry_date);
      window.store.set('google-user-credentials.access_token', credentials.access_token);
      resolve(credentials.access_token); // 这就是想要的 access_token 了
      // 我这是从 new Promise 函数里面复制过来的,所以有 resolve
    })

最后

这可能写得还是有些简略,但是重点都覆盖到了。有不清楚的可以再邮件我。

全文完

感谢阅读