首页 > 解决方案 > 用户使用 chrome.identity.launchWebAuthFlow 登录后,如何在过期前获得新的访问令牌?

问题描述

抱歉,如果以前有人问过这个问题,但我整天都在谷歌上搜索,但没有任何结果。

我正在将 Chrome 身份 API 用于我正在为我的工作构建的 Chrome 扩展程序(与 Google Sheets API 交互),并且我希望为用户保留登录信息,但找不到使用此 API 刷新令牌的地方。

我第一次实现chrome.identity.getAuthToken()并且能够授权对 gSheets API 的请求,当访问令牌过期时问题就来了。我知道,getAuthToken()如果您使用 调用它,再次调用会刷新令牌interactive: false,但前提是您登录的具有您在与弹出窗口的初始交互中授权的相同电子邮件,这不是我想要的,因为在我的浏览器中,我使用我的个人电子邮件登录,我想为扩展程序授权工作电子邮件。因此,1 小时后,我需要请求一个新令牌,该令牌将提示登录弹出窗口,这是一个糟糕的用户体验。

然后我尝试使用chrome.identity.launchWebAuthFlow()端点https://accounts.google.com/o/oauth2/v2/auth知道这launchWebAuthFlow()是针对非 Google 帐户的,尽管它运作良好,据我所知,没有办法在 - 比方说 - 45 分钟后刷新令牌以避免踢出用户。

chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
  switch (request.type) {
    case "login":
      let authURL = "https://accounts.google.com/o/oauth2/v2/auth";
      const clientId = `<CLIENT_ID>`;
      const redirectURL = chrome.identity.getRedirectURL("oauth2");
      const auth_params = {
        client_id: clientId,
        redirect_uri: redirectURL,
        response_type: "token",
        scope: "https://www.googleapis.com/auth/spreadsheets"
      };

      const paramString = Object.keys(auth_params)
        .map(function(k) {
          return k + "=" + auth_params[k];
        })
        .join("&");

      authURL += "?" + paramString;

      chrome.identity.launchWebAuthFlow(
        { url: authURL, interactive: true },
        function(responseURL) {
          if (chrome.runtime.lastError) {
            console.log(chrome.runtime.lastError);
            return;
          }

          if (responseURL) {
            const paramsString = responseURL.substring(
              responseURL.indexOf("#") + 1
            );
            const params = new URLSearchParams(paramsString);

            const paramsObj = () => {
              const obj = {};
              for (var entry of params.entries()) {
                obj[entry[0]] = entry[1];
              }
              return obj;
            };

            const { access_token } = paramsObj();

            sendResponse({
              access_token
            });
          } else {
            console.log(`${responseURL} defined?`);
          }
        }
      );

      return true;
    default:
      console.log("placeholder");
      break;
      }
});

如果这意味着我可以改善用户的用户体验,我愿意放弃 Chrome 身份 API 并使用另一个 OAuth2 流程。

TL;DR:我想在前一个令牌到期前几分钟通过 Chrome 身份 API 或任何其他 OAuth2 实现获得一个新的访问令牌,同时能够使用与登录的 Chrome(人员)不同的 Google 帐户。

标签: google-chromegoogle-chrome-extension

解决方案


我本可以编辑上一个问题,但我要回答它:

access_type=offline有一种方法可以通过使用and发出代码而不是令牌来获取新令牌 response_type:'code'

let authURL = 'https://accounts.google.com/o/oauth2/v2/auth';
const redirectURL = chrome.identity.getRedirectURL("oauth2");
const auth_params = {
  client_id: clientId,
  redirect_uri: redirectURL,
  response_type: 'code',
  access_type: 'offline',
  scope: 'https://www.googleapis.com/auth/spreadsheets',
};
chrome.identity.launchWebAuthFlow({url: authURL, interactive: true}, responseURL => console.log(responseURL))

响应将是一个 URL:

https://<extension_id>.chromiumapp.org/oauth2?code=4/A<code>#

返回的代码可以兑换一个只能使用1次的令牌。https://www.googleapis.com/oauth2/v4/token然后,您使用以下代码段作为请求发送 POST请求:

POST /oauth2/v4/token HTTP/1.1
Host: www.googleapis.com
Content-Type: application/x-www-form-urlencoded

code=4/A<code>&
client_id=your_client_id&
client_secret=your_client_secret&
redirect_uri=https://<extension_id>.chromiumapp.org/oauth2&
grant_type=authorization_code

响应将是一个 JSON 对象,您可以使用它约 1 小时来向 Google API 发出请求:

{
    "access_token": "<access_token>",
    "token_type": "Bearer",
    "expires_in": 3578
}

最后,在访问令牌过期之前,您可以调用launchWebAuthFlow()with interactive: false,它将返回一个新代码,然后您将获得一个新令牌。


推荐阅读