Firebase Auth - createUserWithEmailAndPassword() - 在验证电子邮件之前阻止登录

Posted

技术标签:

【中文标题】Firebase Auth - createUserWithEmailAndPassword() - 在验证电子邮件之前阻止登录【英文标题】:Firebase Auth - createUserWithEmailAndPassword() - prevent login until email is verified 【发布时间】:2021-11-19 13:25:09 【问题描述】:

我希望使用 createUserWithEmailAndPassword() 在 Firebase Auth 中创建一个用户帐户 - 无需登录用户。我希望用户先验证电子邮件地址。直接登录用户会导致很多不需要的副作用。

/signup 页面有以下代码 - 我希望用户在注册后停留在 /signup 页面上,以便能够看到注册消息。

firebase.auth().createUserWithEmailAndPassword(data.email, data.password)
.then((user)=> 
  //Send email verification link
  user.sendEmailVerification()
  //Show message - "Your account was created - please verify using link in email"
  handleStatusMessage(AUTH_SUCCESS)
)
.catch((error)=>...)

app.js 具有以下登录和重定向处理程序

//handle login and redirect
firebase.auth().onAuthStateChanged((user) => 
  if (user) 
    if(!user.emailVerified)
      //Exit if email is not verified
      console.log('auth.js exit')
      //Line 7
    
    store.dispatch(setInitialStore()).then(() => 
      renderApp()
      //Brings user to start page
      if (history.location.pathname === '/login') 
        history.push('/start')
      
    )
 else 
  renderApp()
  //Brings user to /login or /verifyEmail page when logged out
  if(!history.location.pathname.includes('/verifyEmail'))
    history.push('/login')
    

我的问题是:

    用户在成功注册后被重定向,除非我在第 7 行取消执行

    如果我在第 7 行取消执行,用户在离开 /signup 时会卡住

    注销用户会导致 onAuthStateChanged() 触发两次 - 重定向用户

如何在成功创建帐户后将用户保留在 /signup 页面上,同时仍允许用户导航到 /login /verifyEmail 位置?最好处于注销状态。

【问题讨论】:

createUserWithEmailAndPassword 会在成功创建帐户后自动让用户登录,因此您唯一的选择是立即再次将其注销。 嗨@Herohtar!再次注销用户会触发 onAuthStateChanged() 两次 - 我需要处理两种情况以防止用户被重定向和登录。但注销用户是个好主意,因为我不希望用户登录. 【参考方案1】:

我最终做的是添加检查用户在注册期间登录和注销的时间。

signupPage.js

firebase.auth().createUserWithEmailAndPassword(data.email, data.password)
.then((user)=> 
  //Login is triggered --> line 4 in app.js
  user.sendEmailVerification() //Send email verification
  handleStatusMessage(AUTH_SUCCESS) //Show success message
  firebase.auth().signOut() //Logout is triggered --> line 16 in app.js
)
.catch((error)=> ... 

app.js

//handle login and redirect
firebase.auth().onAuthStateChanged((user) => 
  if (user) 
    //** line 4 ** EXIT if logged in from /signup
    if(!isEmailVerified && history.location.pathname.includes('/signup'))
      return
    
    store.dispatch(setInitialStore()).then(() => 
      renderApp()
      //Brings user to start page
      if (history.location.pathname === '/login') 
        history.push('/start')
      
    )
 else 
  //** line 16 ** EXIT if logged out from /signup
  if(history.location.pathname.includes('/signup'))
    return
  
  renderApp()
  //Brings user to /login or /verifyEmail page when logged out
  if(!history.location.pathname.includes('/verifyEmail'))
    history.push('/login')
    

真的希望有一个选项让 createUserWithEmailAndPassword() 能够自动发送电子邮件验证电子邮件并且登录用户避免这种猫捉老鼠的游戏代码。 :)

一个单独的方法,类似于 createUserWithEmailAndPasswordEmailVerificationRequired(),它自动发送电子邮件链接并且不登录用户也可以工作 ;)

【讨论】:

我为此添加了一个功能请求。请点赞以引起更多关注:github.com/FirebaseExtended/flutterfire/discussions/5692【参考方案2】:

Firebase Auth 功能 createUserWithEmailAndPassword 在成功创建帐户后自动登录用户(不需要电子邮件验证)。

如果您需要在没有自动登录的情况下验证新用户注册的电子邮件地址,那么另一种选择是Email Link Authentication

您可以使用 Firebase 身份验证通过向用户发送包含链接的电子邮件来登录用户,他们可以单击该链接进行登录。在此过程中,用户的电子邮件地址也会得到验证。强>

通过电子邮件登录有很多好处:

低摩擦注册和登录。 跨应用程序重复使用密码的风险较低,即使是精心选择的密码也会破坏安全性。 能够在验证用户身份的同时验证用户是否是电子邮件地址的合法所有者。 用户只需要一个可访问的电子邮件帐户即可登录。不需要拥有电话号码或社交媒体帐户的所有权。 用户无需提供(或记住)密码即可安全登录,这在移动设备上可能很麻烦。 以前使用电子邮件标识符(密码或联合身份)登录的现有用户可以升级为仅使用电子邮件登录。例如,忘记密码的用户仍然可以登录,而无需重置密码。

用户通过邮件链接认证成功创建账户后,您可以提供创建密码和link to the existing account的选项。

【讨论】:

嗨@christopher!感谢您的答复!我知道电子邮件链接身份验证选项,但不希望使用该方法。不过,对于其他人来说,我可能是一个不错的选择。我认为在电子邮件+密码注册时缺少电子邮件验证选项是可以在 firebase auth 中改进的。 我以后可能会考虑先使用电子邮件链接登录,然后设置密码+链接帐户的能力!

以上是关于Firebase Auth - createUserWithEmailAndPassword() - 在验证电子邮件之前阻止登录的主要内容,如果未能解决你的问题,请参考以下文章

如何分别从 Firebase Auth 和实时数据库中原子地删除用户和用户的数据?

Firebase 实时数据库不保存注册页面中的数据

新建 Firebase 期间的 UpdateProfile()

输入“用户?”没有成员 UID(Swift 3、Firebase)

Firebase使用电子邮件和密码创建用户给我字符串必须是解包错误

如何知道注册邮箱在 Firebase 中是不是经过验证?