Firebase admin sdk:idToken 或用于授权的自定义令牌验证

Firebase admin sdk: idToken OR custom token verification for authorization

我在登录时在后端服务器上创建自定义令牌,下面是代码:

UserSchema.methods.generateAuthToken = function() {
 var user = this;
 var access = "auth";

 return firebaseAdmin.default
  .auth()
  .createCustomToken(user._id.toHexString())
  .then(function(token) {
    user.tokens = user.tokens.concat([{ access, token }]);
    return user.save().then(() => {
      return token;
    });
  });
};

并将此令牌存储在 mongodb 中,并通过名为“x-auth”的 header 将其发送回客户端,然后将其存储在 cookie 中。

在客户端,使用此令牌登录如下:

axios({
  url: "/api/users/login",
  method: "POST",
  data: {
    email: data.email,
    password: data.password
  }
}).then(res => {
  Cookies.set("x-auth", res.headers["x-auth"], { expires: 7 });
  return firebase
    .auth()
    .signInWithCustomToken(res.headers["x-auth"])
    .then(response => {
      console.log("CA", response);
      response
        .getIdToken()
        .then(idToken => {
          Cookies.set("idToken", idToken, { expires: 7 });
        })
        .catch(e => {});
      dispatch(
        login({
          token: Cookies.get("x-auth")
        })
      );
    });
});

现在为了调用 api 来获取所有用户,我将这些令牌、自定义令牌和 idToken 发送回服务器:

const authenticate = (req, res, next) => {
const token = req.header("x-auth");
const idToken = req.header("idToken");
User.findByToken(token, idToken)
.then(user => {
  if (!user) {
    return Promise.reject({
      message: "no user found with the associated token!"
    });
  }
  req.user = user;
  req.token = token;
  next();
})
.catch(e => {
  res.status(401).send(setErrorMessage(e.message));
});
};

findByToken 如下:

UserSchema.statics.findByToken = function(token, idToken) {
var User = this;
return firebaseAdmin.default
.auth()
.verifyIdToken(idToken)
.then(function(decodedToken) {
  var uid = decodedToken.uid;
  return User.findOne({
    _id: uid,
    "tokens.access": "auth",
    "tokens.token": token
  });
})
.catch(function(e) {
  return Promise.reject(e);
});
};

为什么我必须发送这两个令牌进行授权,这里的概念有什么问题吗?

https://firebase.google.com/docs/auth/admin/verify-id-tokens

Warning: The ID token verification methods included in the Firebase Admin SDKs are meant to verify ID tokens that come from the client SDKs, not the custom tokens that you create with the Admin SDKs. See Auth tokens for more information.

请说明我是否可以验证自定义令牌而不是 idToken 来检索 userId 并将其与数据库匹配,而不是将不同的令牌用于一个目的,或者我在这里做错了,不应存储自定义令牌在 DB 中,还有其他一些方法。

一段时间后,当我尝试获取所有用户时,它显示:

Firebase ID token has expired. Get a fresh token from your client app and try again (auth/id-token-expired). See https://firebase.google.com/docs/auth/admin/verify-id-tokens for details on how to retrieve an ID token.

使用令牌时,您需要区分每个令牌及其用途,并且每个令牌都有相关的属性。

Custom Tokens:这些令牌将在服务器中生成(正如您所做的那样),并在客户端用于对客户端进行身份验证。这些令牌在一小时后过期。

Session ID Token:(我称它为 "Session ID Token" 只是为了区分)当客户端与任何身份验证提供程序进行身份验证时,SDK 将交换用于会话的 ID 令牌的信息.这同样适用于自定义令牌,其中 SDK 将自定义令牌交换为 ID 令牌。 ID 令牌也是短暂的,将在一小时后过期。在获取 ID Token 的同时,SDK 还会收到一个用于 refreshing session ID Token 的刷新 Token。在向 Firebase 发出经过身份验证的请求时使用 ID 令牌。

ID Token for verification:要获取此token,您需要调用函数“getIDToken”(对于Web)。此函数将 return 一个 ID 令牌,它只能用于验证从客户端到您的服务器的请求。与其他令牌类似,这个令牌将在一小时后过期。调用 getIDToken 时,如果当前过期,该函数将请求一个新的。

要验证 ID 令牌,您必须使用上述令牌。如果您尝试使用会话 ID 令牌或自定义令牌,您将收到错误。如果您尝试使用过期的 ID 令牌,这同样适用。

刷新 ID 令牌的所有调用和任务均由 SDK 在幕后处理。

存储这些令牌不是一个好的做法,因为它们将在一小时后过期,如果您调用适当的函数来获取 latets 令牌并传递正确的 ID 令牌以进行验证会更好。

最后,您可以在这些链接中找到用于生成 custom token and the ID Token 进行验证的属性。