【问题标题】:How to use the Firebase refreshToken to reauthenticate?如何使用 Firebase refreshToken 重新认证?
【发布时间】:2016-11-09 01:50:12
【问题描述】:

我使用 JS 库调用 firebase.auth().signInWithEmailAndPassword(email, password) 并返回一个 User 对象。 User 对象包含一个 refreshToken

我使用 curl 'https://docs-examples.firebaseio.com/rest/saving-data/auth-example.json?auth=TOKEN' 调用 Firebase。

令牌最终会过期。为了使它看起来像应用程序(iOSmacOS)具有持久登录,我想刷新令牌,如何使用RESTJS 库来做到这一点?我在文档中找不到任何允许我使用refreshToken 获取新token 的调用。

【问题讨论】:

    标签: firebase firebase-authentication


    【解决方案1】:

    当您从浏览器拨打电话时,.getIdToken(true) 将自动刷新您的令牌。像这样打电话:

    firebase.auth().currentUser.getIdToken(/ forceRefresh / true)
      .then(function(idToken) {
        
      }).catch(function(error) {
    
    });
    

    更多信息在这里https://firebase.google.com/docs/reference/js/firebase.User#getIdToken

    【讨论】:

    • 在新启动应用程序时 currentUser 不会为 NULL 吗?我不知道它在普通浏览器上的情况如何,但我不存储任何 cookie 或本地数据。我只存储 refreshToken 和我特别需要的任何其他内容。
    • 需要先登录才能使用该代码。如果您使用 firebase 登录,它应该可以工作。
    • 这个!但.getToken 现在已弃用,您必须使用.getIdToken
    • 我得到 403(权限被拒绝错误),即使 currentUser 不为空(即用户已登录)。你知道原因吗?
    • @TakamitsuMizutori 我遇到了同样的问题,无法刷新令牌。我通过为我的 Google API 密钥启用令牌服务 API 解决了这个问题。
    【解决方案2】:

    ** 更新 ** 这也记录在 Firebase REST 文档的 Exchange a refresh token for an ID token 部分下:

    https://firebase.google.com/docs/reference/rest/auth/#section-refresh-token


    目前我发现这样做的唯一方法是: https://developers.google.com/identity/toolkit/reference/securetoken/rest/v1/token

    您必须发出 HTTP 请求:

    POSThttps://securetoken.googleapis.com/v1/token?key=YOUR_KEY

    YOUR_KEY 可以在Google developers console > API Manager > Credentials 中找到。它在API Keys 部分下。

    确保请求正文的结构如下:

    grant_type=refresh_token&refresh_token=REFRESH_TOKEN

    其中REFRESH_TOKEN 是他们登录时来自 Firebase 用户对象的刷新令牌。

    您必须设置标题Content-Type: application/json 否则会出现错误(例如“MISSING_GRANT_TYPE”)。

    POST 调用将返回一个新的idToken(以前称为access_token

    【讨论】:

    • 此请求是否适用于刷新 Gmail API 的令牌? @kgaidis
    • @ArtStyle 我对Gmail API不熟悉,所以不知道
    • 这可行,但不幸的是不会触发firebase的onIdTokenChanged监听器......我觉得它应该
    • access_token = id_token
    • 非常感谢你让我开心,我希望我能投票 100 次。我的应用在整个开发过程中一直在喊令牌过期,直到你来帮助我
    【解决方案3】:

    我想这里的大多数人都在寻找一种方法来保持他们的身份验证,而不是在浏览器中,而是在例如在节点后端。事实证明实际上有一种方法可以做到这一点:

    1. 用刷新令牌换取访问令牌(使用 google 的公共 api)
    2. 用访问令牌换取自定义令牌(使用 firebase 函数,见下文)
    3. 使用自定义令牌登录

    下面是代码的精髓:

    const requestP = require('request-promise');
    const fsP = require('fs').promises;
    
    const refreshToken = await fsP.readFile('./refresh_token.txt');
    const res = await requestP.post({
      headers: {'content-type': 'application/x-www-form-urlencoded'},
      url: 'https://securetoken.googleapis.com/v1/token?key=' + firebaseConf.apiKey,
      body: 'grant_type=refresh_token&refresh_token=' + refreshToken,
      json: true
    });
    const customToken = await requestP.post({
      headers: {'content-type': 'text/plain'},
      url: 'https://<yourFirebaseApp>.cloudfunctions.net/createCustomToken',
      body: {token: res.access_token},
      json: true
    });
    await firebaseApp.auth().signInWithCustomToken(customToken);
    

    还有firebase功能:

    export const createCustomToken = functions.https.onRequest(async (request, response) => {
      response.set('Access-Control-Allow-Origin', '*');
    
      try {
          const token = JSON.parse(request.body).token;
          const decodedToken = await admin.auth().verifyIdToken(token);
          const customToken = await admin.auth().createCustomToken(decodedToken.uid);
          response.send(customToken);
      } catch(e) {
          console.log(e);
          response.sendStatus(500);
      }
    });
    

    【讨论】:

    • 在我的情况下,自定义令牌在一小时后过期,您是如何解决这个问题的?
    • 我刚刚再次阅读了您的答案,我想我需要坚持的是刷新令牌而不是自定义令牌。您正在不断创建自定义令牌。
    • 是的,您应该存储刷新令牌,例如:firebaseApp.auth().onAuthStateChanged((user) => { if(user) { fs.writeFileSync('./refresh_token.txt' , refreshToken); } });
    • 但刷新令牌从一个用户更改为另一个用户,如何将其保存在文本文件中?
    • 从刷新令牌创建自定义令牌对公众安全吗?
    【解决方案4】:
    // Create a callback which logs the current auth state
    function authDataCallback(authData) {
      if (authData) {
        console.log("User " + authData['uid'] + " is logged with token" + authData['ie']);
      } else {
        console.log("User is logged out");
      }
    }
    // Register the callback to be fired every time auth state changes
    var ref = new Firebase("https://<YOUR-FIREBASE-APP>.firebaseio.com");
    ref.onAuth(authDataCallback);
    

    事件onAuth将在页面刷新时被调用,如果用户被注销authData将为空,否则不是。您可以在authdata['ie'] 中找到令牌。在下面的屏幕截图中,我在 auth 和 authdata 对象之后打印了令牌,您如何看到 authData['ie'] 和令牌是相似的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-07-26
      • 1970-01-01
      • 1970-01-01
      • 2017-11-23
      • 2020-12-12
      • 1970-01-01
      • 2020-10-13
      相关资源
      最近更新 更多