【问题标题】:Using Firebase Auth with an external database将 Firebase 身份验证与外部数据库一起使用
【发布时间】:2022-01-13 10:06:16
【问题描述】:

我目前正在使用 Firebase 在 React/Node 应用程序中对我的用户进行身份验证,但我还想在我自己的数据库中存储其他用户数据,为此我将 Firebase uid 存储在每个用户上,并且我想就我的实施获得一些意见,以确保我走在正确的轨道上。

我的前端代码如下:

  1. 这用作“继续使用 Google”按钮上的 onClick
const googleSignIn = async () =>
    signInWithPopup(auth, new GoogleAuthProvider());
  1. 当上述弹出承诺完成时,auth.onAuthStateChanged 会在以下useEffect 中触发,这(在登录/注册时)将触发函数applicationAuthentication,传入从 Firebase 返回的用户对象:
  useEffect(() => {
    const unsubscribe = auth.onAuthStateChanged(firebaseUser => {
      if (!firebaseUser) {
        return dispatch(logUserOut());
      }
      return applicationAuthentication(firebaseUser);
    });
    return unsubscribe;
  }, []);
  1. applicationAuthentication 如下所示:
const applicationAuthentication = async (firebaseUser: User) => {
    try {

      const idToken = await firebaseUser.getIdToken();

      const { data } = await axios.get('/api/users/authenticate/signin', {
        headers: {
          Authorization: `Bearer ${idToken}`
        }
      });
      const { user, error } = data;

      if (error) {
        throw new Error(error.message);
      }

      dispatch(logUserIn({ user, accessToken: idToken }));

    } catch (error: any) {
      dispatch(setUserError(error.message));
      console.log(error.message);
    }
};

在我的节点快递服务器中,以下发生在路由/api/users/authenticate/signin;这是我使用数据访问方法findUserByFirebaseUIDcreateUser 与我自己的数据库通信的地方,使用令牌中的uid 检查用户是否存在,如果不存在,则创建一个新用户(注意中间件是首先检查如下):

usersRouter.get(
  '/authenticate/signin',
  async (req: Request, res: Response, next: NextFunction) => {
    try {
      const uid = res.locals.uid; // set by token middlewear function

      let firstLogin = false;
      let user = await findUserByFirebaseId(uid);

      if (!user) {
        firstLogin = true;
        user = await createUser(uid);
      }

      res.json({ user, firstLogin });
    } catch (error) {
      next(error);
    }
  }
);

它使用下面的authenticate中间件函数来验证firebase-admin的用户:

const authenticate = async (
  req: Request,
  res: Response,
  next: NextFunction
) => {
  try {
    const idToken = req.headers.authorization.split(' ')[1];
    const decodedToken = await admin.auth().verifyIdToken(idToken);

    if (decodedToken) {
      const { uid } = decodedToken;
      res.locals.uid = uid;
      return next();
    }
    return res.status(400).json({ message: 'Unauthorized Request' });
  } catch (error) {
    next({ message: 'Invalid Token' });
  }
};

app.use(authenticate);

使用uid 检查我自己的数据库的整个流程看起来是否正确?我是否正确实现了令牌中间件?

我很想听听对此的任何想法!

【问题讨论】:

  • 您想为同一用户存储其他数据吗?喜欢 PII 信息? Firebase Auth 具有自定义字段,您可以在其中添加更多数据,例如另一个对象,并且您可以检索该数据。但是如果你想保存一些不同的东西,比如与用户相关的数据,比如完整的 Item 个性化,你可以只保存 uid,(就像你正在做的那样),它似乎没问题。
  • 我感兴趣的数据基本上是自定义用户数据,例如用户名、角色、youtubeChannelURL 等。这些示例是您所说的“完整项目个性化”吗?
  • 不,我通常指的是完整的个性化和整个个人资料页面,但是没关系,您也可以将这些字段添加到 firebase auth 自定义字段中。

标签: node.js firebase express


【解决方案1】:

是的,您将 ID 令牌从客户端传递到服务器,然后在您的服务器上对其进行解码(在中间件中)以安全地确定 UID 的方式类似于 Firebase 自己的服务执行此操作的方式。

如果您将 ID 令牌传递给其他请求以对其进行授权,请考虑保留最近的原始和解码 ID 令牌的缓存,以防止必须在每个请求上对其进行解码。

【讨论】:

  • 太棒了!谢谢你。我肯定会考虑缓存令牌。
猜你喜欢
  • 2017-05-10
  • 2019-06-28
  • 1970-01-01
  • 2016-03-01
  • 1970-01-01
  • 2020-07-22
  • 1970-01-01
  • 2021-06-14
  • 2018-07-19
相关资源
最近更新 更多