如何将 Firebase Auth Token 从客户端传递到服务器?

Posted

技术标签:

【中文标题】如何将 Firebase Auth Token 从客户端传递到服务器?【英文标题】:How to pass Firebase Auth Token from client to server? 【发布时间】:2017-08-28 23:13:49 【问题描述】:

我正在处理的网站使用 Firebase 身份验证,并且登录的不同用户对于他们可以访问哪些页面具有不同的权限。

登录的设置方式和这个post类似:

    用户使用两个参数登录 - “id”和“email” 服务器使用这些来创建一个自定义“uid”,然后使用 Firebase Admin SDK 创建一个发送回客户端的自定义令牌。 客户端使用 javascript Firebase SDK - firebase.auth().signInWithCustomToken() 登录 现在用户已登录,他们可以点击不同的页面 - 即“/foo”、“/bar”

我遇到的问题是,当他们访问新页面时,我试图将令牌从客户端传递回服务器(几乎与它在 Firebase Doc 中的完成方式相同),验证令牌并检查它是否有权查看该网页。

我正在尝试找出最好的(也是最安全的)方法来做到这一点。我考虑过以下选项:

使用令牌构造一个 URL,但我听说这不是一个好的做法,因为令牌会暴露出来,会话劫持变得容易得多。

我一直在尝试在请求标头中传递令牌,但据我了解,当用户单击指向不同页面的链接(或者如果它在 javascript 中重定向)时,您无法添加标头。同样的问题也适用于使用 POST。

当用户单击指向不同页面的链接时,我可以做些什么来安全地将这些信息传递给服务器并检查权限?

【问题讨论】:

您可以将其设置在 cookie 中。这就是我可能会做的。 嗨,迈克尔,非常感谢您的回复。我需要服务器上的信息,但会话是我没有想到的。但这似乎不起作用,因为即使我将客户端的令牌 自定义 uid 存储在服务器上,客户端仍然需要发送其中一个才能访问正确的会话数据.这仍然使会话劫持非常容易.. 我也遇到了同样的问题,你是怎么解决的? 【参考方案1】:

您可以通过以下方式获取客户端的accessToken(idToken):

var accessToken = null;

firebase.auth().currentUser
    .getIdToken()
    .then(function (token) 
        accessToken = token;
    );

并将其传递到您的请求标头中:

request.headers['Authorization'] = 'Bearer ' + accessToken;

然后在您的服务器端使用您喜欢的方法获取令牌并使用 Firebase Admin SDK 对请求进行身份验证,例如 (Node.js):

firebaseAdmin.auth()
    .verifyIdToken(accessToken)
    .then(decodedIdToken => 
        return firebaseAdmin.auth().getUser(decodedIdToken.uid);
    )
    .then(user => 
        // Do whatever you want with the user.
    );

【讨论】:

您是否真的必须创建令牌才能让我在客户端检索它?【参考方案2】:

现在,我们似乎打算使用httpsCallable() 客户端来获得一个预先授权的对象来与您的端点通信。

例如:

// # ./functions/index.js
exports.yourFunc = functions.https.onCall((data, context) => 
  // Checking that the user is authenticated.
  if (!context.auth) 
    // Throwing an HttpsError so that the client gets the error details.
    throw new functions.https.HttpsError('failed-precondition', 'The function must be called ' +
      'while authenticated.');
  
  // ... rest of your method
);
// ./src/models/addMessage.js
const firebase = require("firebase");
require("firebase/functions");

firebase.initializeApp(
  apiKey: '### FIREBASE API KEY ###',
  authDomain: '### FIREBASE AUTH DOMAIN ###',
  projectId: '### CLOUD FUNCTIONS PROJECT ID ###'
  databaseURL: 'https://### YOUR DATABASE NAME ###.firebaseio.com',
);
var functions = firebase.functions();

// This is the new code:
var yourFunc = firebase.functions().httpsCallable('yourFunc');
yourFunc(foo: bar).then(function(result) 
  // ...
);


来自firebase documentation

【讨论】:

以上是关于如何将 Firebase Auth Token 从客户端传递到服务器?的主要内容,如果未能解决你的问题,请参考以下文章

firebase:admin.auth().updateUser() 导致 auth/user-token-expired

如何修复 Firebase Auth 仅在刷新后工作?

Flutter-Firebase phone Auth 总是在 iOS 上返回 Token mismatch

如何从 firebase_auth 获取令牌

如何从 firebase.auth().onAuthStateChanged 中提取数据

如何在 Flutter 中从 Firebase Auth 获取用户 ID?