如何从onAuthStateChanged中获取UserCredential以判断用户首次登录?
解决方法
onAuthStateChanged的回调里无法直接获取UserCredential,因为这个监听触发的场景包括页面刷新后用户保持登录的情况,这时候并没有登录流程中产生的UserCredential对象。要判断用户是否首次登录,得换个思路:
- 第一步:在各个登录方法(Google、Facebook、邮箱登录)的回调里,调用
getAdditionalUserInfo(userCredential)拿到首次登录标记,然后把这个信息存起来(比如存到Firebase Firestore的用户文档里,或者设置到用户的自定义Claims中)。 - 第二步:在onAuthStateChanged的回调里,从存储的位置读取这个首次登录的信息,再传给
onLoginSuccess。
1. 登录时存储首次登录信息
以Google登录为例:
async function signInWithGoogle() { const provider = new GoogleAuthProvider(); const userCredential = await signInWithPopup(auth, provider); const additionalInfo = getAdditionalUserInfo(userCredential); // 如果是首次登录,把标记存到Firestore if (additionalInfo.isNewUser) { await setDoc(doc(db, "users", userCredential.user.uid), { isFirstLogin: true, // 可添加其他用户信息 }); } else { // 非首次登录可更新登录时间等信息 await updateDoc(doc(db, "users", userCredential.user.uid), { lastLogin: new Date() }); } }
2. 在onAuthStateChanged中读取信息并传递
修改你的watchAuthChanges函数:
export const watchAuthChanges = (onLoginSuccess, onLogoutSuccess, onError) => { onAuthStateChanged(auth, async (user) => { if (user) { const token = await getIdToken(user); const refreshToken = async () => { return await getIdToken(user, true); }; // 从Firestore读取用户的首次登录信息 const userDoc = await getDoc(doc(db, "users", user.uid)); const userData = userDoc.exists() ? userDoc.data() : null; const isFirstLogin = userData?.isFirstLogin || false; // 把额外信息传给onLoginSuccess onLoginSuccess(user, token, refreshToken, { isFirstLogin }); } else { onLogoutSuccess(); } }, (error) => { onError(error); }); };
补充方案:用自定义Claims存储标记
如果不想用Firestore,也可以通过自定义Claims存储首次登录状态:
// 登录时设置自定义Claims if (additionalInfo.isNewUser) { await setCustomUserClaims(userCredential.user.uid, { isFirstLogin: true }); } // 在onAuthStateChanged中读取 const userClaims = await user.getIdTokenResult(); const isFirstLogin = userClaims.claims.isFirstLogin || false;
这样不管是首次登录触发,还是页面刷新后的登录状态,都能拿到首次登录的标记,无需在多个代码路径重复处理登录逻辑。
内容的提问来源于stack exchange,提问作者Dave
相关产品推荐
相关产品推荐

