【问题标题】:Firebase Google Auth offline access_type in order to get a token refreshFirebase Google Auth 离线 access_type 以获得令牌刷新
【发布时间】:2015-03-09 13:19:27
【问题描述】:

我们正在使用带有 google 身份验证的 firebase。我们选择 Google 是因为我们的应用程序会调用 Google API。我们使用从 firebase 返回的授权负载中包含的 access_token 来授权这些 api 调用。但是,我们无法弄清楚如何在 access_token 过期后刷新它。根据谷歌的说法,我们应该假设 access_token 可能由于各种原因而过期。

因此,(据我了解)我们需要一种方法来刷新此令牌,而无需强制用户重新授权。理想情况下,我可以在请求 firebase auth 时请求离线 access_type ......但我不知道如何做到这一点(没有再次触发 firebase.authWithOAuthPopup(...) ,我们绝对不想作为用户会话做显然仍然有效。

是否可以通过 Firebase 获取离线 access_type Google oauth 令牌,以便 Google 返回 refresh_token (https://developers.google.com/accounts/docs/OAuth2WebServer#formingtheurl)?使用 refresh_token,我想我可以为 api 调用获取一个新的 access_token。

我正在尝试这个,但它绝对不支持:

this.firebase.authWithOAuthPopup("google", this.authenticateGoogle.bind(this), {
    access_type: 'offline', <-- not passed to Google
    scope: 'https://www.googleapis.com/auth/userinfo.profile, https://www.googleapis.com/auth/devstorage.read_write'
});

https://www.googleapis.com/oauth2/v1/tokeninfo?access_token=abcd 的所有调用都将 access_type 显示为在线。

谢谢

【问题讨论】:

  • 很遗憾,目前无法通过 Firebase 获取 Google OAuth 刷新令牌,但我们已经知道并希望解决此问题。
  • 既然这回答了这个问题,那应该是一个答案。

标签: firebase google-oauth firebase-security


【解决方案1】:

暂时解决。根据来自 Firebase 的 Rob DiMarco 的说法:“很遗憾,目前无法通过 Firebase 获取 Google OAuth 刷新令牌,尽管我们已经知道并希望解决这个问题。”

【讨论】:

  • 有什么更新吗?我的应用程序确实需要此功能。我仍然对 Firebase 为什么会这样做感到困惑。这似乎是一个非常无知的决定。
【解决方案2】:

在您的客户端代码中使用不同的 OAuth 2.0 库, 能够使用access_type=offline 发送授权请求。在 OAuth 2.0 与 Google 的交互中,没有任何特定于 firebase 的内容可以为您获取访问令牌和刷新令牌,因此您可以依赖单独的代码来处理该部分。当然,您需要专门为 Firebase 提供范围(我相信至少是“https://www.googleapis.com/auth/freebase”),但这对于任何 OAuth 2.0 客户端库来说都不是问题。

【讨论】:

  • 所以我一直在思考这种方法。如果没有刷新令牌,我将无法使用谷歌现有的 oauth 令牌。所以我必须提出一个新的oauth请求......这可能是另一个登录。那并不理想。所以这种方法的一些缺点是a)我必须将自己的“自定义”身份验证滚动到firebase,b)需要服务器端组件来生成JWT。然后 c) 我必须在我的 ember 应用程序中实现身份验证并将其与 google 连接起来(尽管 torii (vestorly.github.io/torii) 看起来它可能适用于此)。
【解决方案3】:

一种将服务器端实施要求降至最低的解决方案。

TL:DR; 使用Google Sign-In for Websites 库生成身份验证凭据。使用身份验证凭据登录 Firebase,并将离线访问交换代码发布到您的服务器。

客户端

客户端我通过包含以下内容实现了Google Sign-In for Websites

<script src="https://apis.google.com/js/platform.js?onload=loadAuth2" async defer></script>
<script>
  function loadAuth2 () {
    gapi.load('auth2', function() {
      gapi.auth2.init({
        client_id: 'your firebase Web client ID',
        cookie_policy: 'single_host_origin',
        scope: 'profile ...'
      });
    });
  }
</script>

注意:范围应该是您需要的访问范围的空格分隔列表。

假设 Firebase 已加载,我的登录点击处理程序是:

<script>
  function login() {
    const auth = gapi.auth2.getAuthInstance();
    auth.then(() => {
      auth.grantOfflineAccess({
        'redirect_uri': 'postmessage',
        'prompt': 'concent',
        'approval_prompt': 'force',
      }).then(offlineAccessExchangeCode => {
        // send offline access exchange code to server ...

        const authResp = auth.currentUser.get().getAuthResponse();
        const credential = firebase.auth.GoogleAuthProvider.credential(authResp.id_token);
        return firebase.auth().signInWithCredential(credential);
      }).then(user => {
        // do the thing kid! 
      });
    });
  }
</script>

使用'redirect_uri': 'postmessage' 调用auth.grantOfflineAccess 会导致Google auth2 库通过window.postMessage 将身份验证凭据传回您的网络应用程序。 See here for the auth2 library reference.

在我的应用程序的其他地方,我正在监听 Firebase 身份验证状态的变化。

firebase.auth().onAuthStateChanged(user => {
  if (user) {
    // navigate to logged in state
  } else {
    // navigate to login page
  }
});

服务器端

我将POSTofflineAccessExchangeCode(看起来像{"code": "..."})发送到我的服务器,以交换当前经过身份验证的用户的凭据,其中包括刷新令牌。虽然客户端你可以访问firebase.auth().currentUser.refreshToken 这个令牌对我不起作用(也许有人可以告诉我我在这里弄错了:D)

我在 Python 中的服务器端代码如下。请注意,Google SDK 是为大多数 Google 服务自动生成的,因此以下代码应该可以轻松翻译成它们支持的任何语言。

from oauth2client import client
// ...
// assuming flask
@app.route("/google/auth/exchange", methods=['POST'])
def google_auth_exchange():
    auth_code = request.get_json()['code']
    credentials = client.credentials_from_clientsecrets_and_code(
        'config/client_secret.json', ['profile', '...'], auth_code)

    print(credentials.refresh_token)

差不多就是这样。如果您需要离线访问,我会假设您有一个服务器或一些服务器端代码,因此希望实现路由离理想的解决方案不会太远。

测序

注意: GCLID 解析器是我目前正在从事的一个项目,需要它。

【讨论】:

    【解决方案4】:

    已解决:Google OAuth Refresh Tokens not returning Valid Access Tokens

    您必须在服务器上处理身份验证,然后向客户端返回一个 idtoken,并在服务器上通过身份验证后使用 firebase 登录。这样您就可以在后端获取刷新令牌,将它们存储在数据库中的用户(来自服务器)上,然后使用该刷新令牌重新进行身份验证。

    【讨论】:

      猜你喜欢
      • 2020-01-28
      • 1970-01-01
      • 2018-07-18
      • 2015-07-03
      • 2012-11-26
      • 2013-09-02
      • 2019-12-01
      • 2023-03-31
      • 2013-03-16
      相关资源
      最近更新 更多