android Firebase电子邮件验证工作不正常

fquxozlt  于 2023-03-16  发布在  Android
关注(0)|答案(7)|浏览(130)

"我拥有的一切"
我在我的应用中使用Firebase Authentication,用户可以使用Email & Password注册。如果用户没有验证他们的电子邮件,我会禁用一些功能,直到他们验证他们的电子邮件。
我还有一个按钮来显式触发验证邮件,它只是调用,sendEmailVerification()。它工作得很完美,验证邮件总是被发送。

问题所在

用户收到了验证邮件,但当他/她验证邮件并返回应用程序时,isEmailVerified()始终为false。因此,尽管用户已验证其电子邮件,但我的应用程序仍不允许用户使用所有功能。
但是如果他们注销并重新登录,isEmailVerified()立即返回true。但是注销用户并重新登录不好吗?
是Firebase的bug还是我做错了什么

0yg35tkg

0yg35tkg1#

嘿,我知道这是一个很老的线程,但什么解决了我的问题FIRAuth.auth()?.currentUser.reload(completion: { (error) in ... })
对于任何面临这个问题的人。而且我正在使用最新的Firebase版本10. 0. 1

更新

自从我发布我的解决方案以来,Firebase已经更改了它们的函数名。
请注意,通过添加stateDidChangeListener. Auth.auth()?,可以观察到当前用户状态的所有更改。currentUser不会立即更新,因此我所做的是将当前用户保存到我自己创建和维护的全局变量中。

Auth.auth().addStateDidChangeListener { (auth, user) in
 // ...
}

无论何时调用Auth.auth()?.currentUser.reload(),都会通过stateDidChangeListener传递一个刷新的、随时可用的用户对象。
然后,您可以检查任何更新的数据(即电子邮件验证)

5w9g7ksd

5w9g7ksd2#

下面是我使用react-native解决这个问题的方法:

const user = firebase.auth().currentUser;
user.reload().then(() => {
  console.log({emailVerified: user.emailVerified})
})

如果用户将应用程序从后台带到前台,我将其与AppState结合使用以运行重新加载。

kcrjzv8t

kcrjzv8t3#

就这么办吧:

FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
user.reload();

if(user.isEmailVerified())
{
     .....
      ...
}
w3nuxt5m

w3nuxt5m4#

您必须在发送验证电子邮件后重新加载您的Firebase用户。

mAuth.createUserWithEmailAndPassword(inputEmail.getText().toString(), inputPassword.getText().toString())
    .addOnCompleteListener(ResetPasswordActivity.this, task -> {
        user = mAuth.getCurrentUser();user.reload();
        if(mAuth.getCurrentUser().isEmailVerified()){
            next();//intent to next activity
        } else {               
            mAuth.getCurrentUser().sendEmailVerification().addOnCompleteListener(task1 -> System.out.println("function"));
        }
        if (task.isSuccessful()) {
            user = mAuth.getCurrentUser();
            System.out.println(user.isEmailVerified());
        }
    }

就是这样!

rks48beu

rks48beu5#

订阅用户auth-state可能会解决此“bug”。

constructor(
    public afAuth: AngularFireAuth,
    public router: Router
  ) {
    this.afAuth.authState.subscribe(user => {
      // here you verify if the user is emailVerified BEFORE storing him in local storage.
      // if you want to keep storing the user even
      // before email verification, you need to work out this logic
      if (user && user.emailVerified) {
        this.userData = user;
        localStorage.setItem('user', JSON.stringify(this.userData));
        JSON.parse(localStorage.getItem('user'));
      } else {
        localStorage.setItem('user', null);
        JSON.parse(localStorage.getItem('user'));
      }
    })
  }
ssm49v7z

ssm49v7z6#

在我使用react-native-firebase的情况下,订阅onAuthStateChanged不会更新emailVerified,订阅onUserChanged也不会更新onUserChanged,唯一有效的方法是调用user.reload()

自动触发user.reload()

但是,我不希望用户按下另一个按钮,这样我就可以触发user.reload()。我希望它自动触发。这个问题已经讨论过here,似乎深度链接可以允许自动触发user.reload()。但我不喜欢深度链接。因此,这里是我的解决方案。
注册用户后,进入电子邮件验证屏幕,告诉用户系统正在等待用户验证他/她的电子邮件(如下所示)。在此屏幕上,我们通过setInterval和一个虚拟状态变量每秒更新一次屏幕。每次更新后,user.reload()都会自动调用。

const EmailVerScreen = (props: PropsT) => {
  const [user, setUser] = React.useState();
  const [dummy, setDummy] = React.useState(true);

  React.useEffect(() => {
    const subscriber = auth().onAuthStateChanged(curUser => setUser(curUser));
    return subscriber; // unsubscribe on unmount
  });

  React.useEffect(() => {
    const interval = setInterval(async () => {
      setDummy(!dummy);
      try {
        if (user) {
          await user.reload();
        }
      } catch (error) {
        console.log(error);
      }
    }, 1000);
    return () => clearInterval(interval);
  });

  return (
    <View>
      <Text>{`Dummy is ${dummy ? 'True' : 'False'}`}</Text>
      <Text>
        {user
          ? user.emailVerified
            ? 'Verified'
            : 'Not verified'
          : 'User unavailable'}
      </Text>
    </View>
  );
};
6mw9ycah

6mw9ycah7#

我终于明白了,Firebase从auth函数中移除了auth.applyActionCode,并将电子邮件验证移到了它的REST API中,下面是文档链接。https://firebase.google.com/docs/reference/rest/auth#section-verify-password-reset-code
如果您使用的是NextJS,您可以使用路由器查询来解析发送给用户的电子邮件验证链接,并从中获取ooBcode和ApiKey,如下所示:

const router = useRouter()
const { oobCode, apiKey } = router.query

然后,您需要向REST API发出POST请求,以验证这两个元素,如下所示。

const res = await fetch(`https://identitytoolkit.googleapis.com/v1/accounts:update?key=${apiKey}`, {
        method: 'POST',
        headers: {
        'Accept': 'application/json',
        'Content-Type': 'application/json',
        },
        body: JSON.stringify({
        oobCode: oobCode
        })
    })

最后,您将返回一个响应对象,该对象将用户的电子邮件验证为“true”

if(!res) return;
let data = await res.json()
   console.log(data)

相关问题