Firebase管理员SDK:idToken或用于授权的自定义令牌验证

Vip*_*pul 4 javascript access-token firebase firebase-authentication firebase-admin

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

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;
    });
  });
};
Run Code Online (Sandbox Code Playgroud)

并将此令牌存储在mongodb中,然后通过名为“ x-auth”的标头将其发送回客户端,然后将其存储在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")
        })
      );
    });
});
Run Code Online (Sandbox Code Playgroud)

现在,为了调用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));
});
};
Run Code Online (Sandbox Code Playgroud)

并且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);
});
};
Run Code Online (Sandbox Code Playgroud)

为什么我必须同时发送这两个令牌以进行授权,所以这里的概念有什么问题。

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

警告:Firebase Admin SDK中包含的ID令牌验证方法旨在验证来自客户端SDK的ID令牌,而不是您使用Admin SDK创建的自定义令牌。有关更多信息,请参见身份验证令牌。

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

现在,当我尝试获取所有用户之后,它说:

Firebase ID令牌已过期。从您的客户端应用中获取新令牌,然后重试(auth / id-token-expired)。有关如何检索ID令牌的详细信息,请参见https://firebase.google.com/docs/auth/admin/verify-id-tokens

Ger*_*rdo 5

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

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

会话ID令牌:(我将其称为“会话ID令牌”只是为了与众不同)。当客户端通过任何身份验证提供程序进行身份验证时,SDK都会交换信息以获取用于会话的ID令牌。自定义令牌也是如此,其中SDK会将自定义令牌交换为ID令牌。ID令牌也是短暂的,将在一小时后过期。获取ID令牌时,SDK还会收到刷新令牌,该刷新令牌用于刷新会话ID令牌。对Firebase进行身份验证的请求时使用ID令牌。

用于验证的ID令牌:要获取此令牌,您将需要调用函数“ getIDToken ”(对于Web)。此函数将返回一个ID令牌,该ID令牌仅可用于验证从客户端到服务器的请求。与其他令牌类似,该令牌在一小时后失效。调用getIDToken时,如果当前过期,该函数将请求一个新的ID。

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

所有用于刷新ID令牌的调用和任务都由后台的SDK处理。

存储这些令牌不是一个好习惯,因为它们将在一小时后过期,如果您调用适当的函数来获取代码令牌并传递要验证的正确ID令牌,则更好。

最后,您可以在这些链接中找到用于生成自定义令牌ID令牌以进行验证的属性。