如何在设置 authContext 和登录状态之前等待 cookie。反应,火力基地

时间:2021-05-20 01:47:43

标签: reactjs firebase express token

我有一个 createUser 函数,它发送一个 axios req 来表达,并需要一些时间来完成创建一个经 Firebase 身份验证的用户,创建一个令牌并将令牌作为 cookie 发送回用户。

我还有一个 getLoggedIn 函数,它接收 cookie 并将其发送给 express 以进行身份​​验证,然后相应地调整我的 authContext。

我的函数如下所示:await createUser(registerData ).then(() => getLoggedIn())

我的问题是 getLoggedIn() 在 createUser 完成发回 cookie 之前被提前调用。知道如何解决这个问题吗?有没有办法监听 cookie 的变化?我没有看到其他人这样做,我的方法一般是错误的吗?

感谢您的帮助。

新建用户表单

 const { getLoggedIn, loggedIn } = useContext(AuthContext);

  const register = async (e) => {
    e.preventDefault();
     const registerData = {
      email,
      password,
      passwordVerify,
    };
    try {
      await createUser(registerData).then(() => getLoggedIn());
    } catch (err) {
      console.log(err);
    }
  }};

创建用户

export const createUser = async (props) => {
      console.log("New User Creation Initiated", props);
      const { email, password, passwordVerify } = props;
      let userObject = { tokenId: null };
    
      try {
        await firebase
          .auth()
          .createUserWithEmailAndPassword(email, password)
          .then(({ user }) => {
            console.log("createUserWithEmailAndPassword", user);
            user
              .getIdToken()
              .then((tokenId) => {
                userObject = { tokenId: tokenId };
                axios.post(`${domain}/auth`, userObject);
              })
              .catch((err) => console.log("new user error", err));
           })
          .catch((err) => {
            console.log("createUser Error", err);
          });
        return;
      } catch (err) {
        console.log("New User Creation Error: ", err);
      }
    };

验证上下文

const AuthContextProvider = (props) => {
  console.log("AuthContextProvider Initiated");

  const [loggedIn, setLoggedIn] = useState(null);

  const getLoggedIn = async () => {
    console.log("getLoggedIn Initiated");
    let validatedUser = await axios.get(`${domain}/auth/loggedIn`);
    console.log("AuthContextProvider validatedUser", validatedUser);
    setLoggedIn(validatedUser.data);
  };

  useEffect(() => {
    getLoggedIn();
  }, []);

  return (
    <AuthContext.Provider value={{ loggedIn, getLoggedIn }}>
      {props.children}
    </AuthContext.Provider>
  );
 };

快递

router.post("/", async (req, res) => {
  console.log("---User signup initiated---");

  try {
    const { tokenId } = req.body;
    console.log("tokenId passed from frontend: ", tokenId);
    admin
      .auth()
      .verifyIdToken(tokenId)
      .then((decodedToken) => {
        const { email, uid } = decodedToken;
        console.log("Fetched UID: ", uid);
        console.log("Fetched email: ", email);
        const Users = db.collection("users");
        Users.doc(`${uid}`).set({
          email: email,
          posts: [],
        });
        console.log("---jwt signing initiated---");

        const token = jwt.sign(
          {
            user: { email, uid },
          },
          process.env.JWT_SECRET
        );
        console.log("token log: ", token);

        return res
          .cookie("token", token, {
            httpOnly: true,
            sameSite: "none",
            secure: true,
          })
          .send();
      });
  } catch (err) {
    console.log(err);
  }
});

router.get("/loggedIn", (req, res) => {
  console.log("login validation initiated");
  try {
    const token = req.cookies.token;
    if (!token) {
      console.log("no token cookie");
      return res.json(null);
    }

     const validatedUser = jwt.verify(token, process.env.JWT_SECRET);
    console.log("Token cookie: ", validatedUser);

    res.json(validatedUser);
  } catch (err) {
    console.log("loggedIn", err);
  }
});

2 个答案:

答案 0 :(得分:0)

您可以在 AuthContext 中像这样使用 onAuthStateChanged。

const AuthContextProvider = (props) => {
  console.log("AuthContextProvider Initiated");

  const [loggedIn, setLoggedIn] = useState(null);

  const getLoggedIn = async () => {
    console.log("getLoggedIn Initiated");
    let validatedUser = await axios.get(`${domain}/auth/loggedIn`);
    console.log("AuthContextProvider validatedUser", validatedUser);
    setLoggedIn(validatedUser.data);
  };
  
  const handleAuthStateChanged = user => {
    if(user) { //user login
      getLoggedIn()
    } else { //user logout
      setLoggedIn(null)
    }
  }

  useEffect(() => {
    const unsubscribe = firebase.auth().onAuthStateChanged((user) => {
      handleAuthStateChanged(user)
    })
    return unsubscribe
  }, []);
  

  return (
    <AuthContext.Provider value={{ loggedIn, getLoggedIn }}>
      {props.children}
    </AuthContext.Provider>
  );
};

答案 1 :(得分:0)

在我的 createUser 函数中,我移动了 axios 调用并将其返回到 firebase.auth() 承诺序列之外。现在似乎可以工作了。

export const createUser = async (props) => {
  console.log("New User Creation Initiated", props);
  const { email, password, passwordVerify } = props;
  let userObject = { tokenId: null };

  try {
    await firebase
      .auth()
      .createUserWithEmailAndPassword(email, password)
      .then(({ user }) => {
        console.log("createUserWithEmailAndPassword", user);
        user
          .getIdToken()
          .then((tokenId) => {
            userObject = { tokenId: tokenId };
          })
          .catch((err) => console.log("new user error", err));
      })
      .catch((err) => {
        console.log("createUser Error", err);
      });
    return axios.post(`${domain}/auth`, userObject);
  } catch (err) {
    console.log("New User Creation Error: ", err);
  }
};