Firebase Google Auth离线access_type以获取令牌刷新

时间:2015-01-11 18:46:11

标签: firebase google-oauth firebase-security

我们正在使用带有Google身份验证的firebase。我们选择Google是因为我们的应用程序会调用Google API。我们使用从firebase返回的授权有效负载中包含的access_token授权这些api调用。但是,我们无法确定如何在access_token到期后刷新它。根据Google的说法,我们应该假设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显示为在线。

由于

3 个答案:

答案 0 :(得分:6)

最小化服务器端实现要求的解决方案。

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>

使用auth.grantOfflineAccess致电'redirect_uri': 'postmessage'会导致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
  }
});

服务器端

POST offlineAccessExchangeCode(看起来像{"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解析器是我目前正在处理的项目,需要这样做。

答案 1 :(得分:4)

现在解决了。根据Firebase的Rob DiMarco:&#34;很遗憾,目前无法通过Firebase获取Google OAuth刷新令牌,尽管这是我们已经了解并希望修复的内容。 &#34;

答案 2 :(得分:1)

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