在使用chrome.identity.launchWebAuthFlow用户登录后,如何在过期之前获得新的访问令牌?

时间:2018-07-14 06:58:19

标签: google-chrome google-chrome-extension

很抱歉,是否曾经有人问过这个问题,但是我整天都在搜寻Google,但是没有任何结果。

我正在为Chrome扩展程序使用Chrome Identity API(我正在为我的工作而构建(与Google Sheets API进行交互),并且我希望保留用户的登录信息,但是使用该API刷新令牌无处可去被发现。

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

然后,我尝试使用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 Identity API并使用其他OAuth2流程。

TL; DR:我希望在上一个令牌过期前几分钟,通过Chrome Identity API或任何其他OAuth2实现获取一个新的访问令牌,同时能够使用不同于已登录Chrome的Google帐户(人)。

2 个答案:

答案 0 :(得分:1)

通过代码获取新令牌是错误的方式。相反,刷新令牌旨在在旧令牌过期后获取新令牌。

  1. 交换刷新和访问令牌的代码。

    https://developers.google.com/identity/protocols/oauth2/web-server?hl=en#exchange-authorization-code
    
  2. 保存刷新令牌。当前访问令牌过期时,通过刷新令牌获取新令牌。

    https://developers.google.com/identity/protocols/oauth2/web-server?hl=en#offline
    

祝编码顺利。

答案 1 :(得分:0)

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

有一种方法可以通过发出代码而不是使用令牌来获取新令牌 access_type=offlineresponse_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次的令牌。然后,您将POST请求发送到https://www.googleapis.com/oauth2/v4/token,并以以下代码段作为请求:

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()调用interactive: false,它将返回一个新代码,并获得一个新令牌。

相关问题