简体   繁体   English

Firebase:Email 验证链接总是过期,即使验证有效

[英]Firebase: Email verification link always expired even though verification works

I'm trying to set up an email verification flow in my project, but I can't seem to get it right.我正在尝试在我的项目中设置 email 验证流程,但我似乎无法正确处理。

How my flow works now is the user enters their credentials (email and password), which are used to create a new firebase user.我的流程现在的工作方式是用户输入他们的凭据(电子邮件和密码),这些凭据用于创建新的 firebase 用户。 Then, once that promise is resolved, it sends an email verification link to the new user that was created.然后,一旦 promise 得到解决,它就会向创建的新用户发送 email 验证链接。 The code looks like this:代码如下所示:

async createUser(email: string, password: string) {
    try {
      console.log("Creating user...");
      const userCredentials = await createUserWithEmailAndPassword(
        auth,
        email,
        password
      );
      console.log("Successfully created user");
      const { user } = userCredentials;
      console.log("Sending email verification link...");
      await this.verifyEmail(user);
      console.log("EMAIL VERIFICATION LINK SUCCESSFULLY SENT");
      return user;
    } catch (err) {
      throw err;
    }
  }

  async verifyEmail(user: User) {
    try {
      sendEmailVerification(user);
    } catch (err) {
      throw err;
    }
  }

The link is sent through fine, but once I press on it, I'm redirected to a page that says this:该链接可以正常发送,但是一旦我按下它,我就会被重定向到一个显示以下内容的页面:

在此处输入图像描述

Strangely, the user's email is verified after this, in spite of the error message displayed.奇怪的是,尽管显示了错误消息,但用户的 email 在此之后得到了验证。 Any idea why this is happening?知道为什么会这样吗?

Update:更新:
I managed to figure it out.我设法弄清楚了。 The email provider I'm using is my university's, and it seems to be preventing the verification link from working properly.我使用的 email 提供商是我大学的,它似乎阻止了验证链接正常工作。 I did try with my personal email to see if that was the case, but I wasn't seeing the verification link appearing there.我确实尝试过使用我的个人 email 来查看是否是这种情况,但我没有看到验证链接出现在那里。 I eventually realized that it was because it was being stored in the spam folder.我最终意识到这是因为它被存储在垃圾邮件文件夹中。 It's working on other email providers, though, ideally, I'd want it to work on my university's email provider (the emails that users sign up with are supposed to be exclusively student emails).它适用于其他 email 提供商,但理想情况下,我希望它适用于我大学的 email 提供商(用户注册的电子邮件应该是专门的学生电子邮件)。 Any ideas how I could resolve this?有什么想法可以解决这个问题吗?

I eventually figured out that the issue was with my email provider.我最终发现问题出在我的 email 提供程序上。 I was using my student email, which the university provides, and I imagine they've placed rigorous measures in place to secure them as much as possible.我正在使用我的学生 email,这是大学提供的,我想他们已经采取了严格的措施来尽可能地保护他们。 I have no idea what was preventing it from working, but I managed to figure out a workaround.我不知道是什么阻止了它工作,但我设法找到了一种解决方法。

In brief, I changed the action URL in the template (which can be found in the console for your Firebase project in the Authentication section, under the Templates tab) to a route on my website titled /authenticate.简而言之,我将模板中的操作 URL(可以在您的 Firebase 项目的控制台中的模板选项卡下的身份验证部分中找到)更改为我网站上标题为 /authenticate 的路由。 I created a module to handle email verification.我创建了一个模块来处理 email 验证。 Included in it is a function that parses the URL, extracting the mode (email verification, password reset, etc.), actionCode (this is the important one. It stores the id that Firebase decodes to determine if it's valid), continueURL (optional), and lang (optional). Included in it is a function that parses the URL, extracting the mode (email verification, password reset, etc.), actionCode (this is the important one. It stores the id that Firebase decodes to determine if it's valid), continueURL (optional ) 和lang (可选)。

export const parseUrl = (queryString: string) => {
  const urlParams = new URLSearchParams(window.location.search);
  const mode = urlParams.get("mode");
  const actionCode = urlParams.get("oobCode");
  const continueUrl = urlParams.get("continueUrl");
  const lang = urlParams.get("lang") ?? "en";
  return { mode, actionCode, continueUrl, lang };
};

I created another method that handles the email verification by applying the actionCode from the URL using Firebase's applyActionCode .我创建了另一种处理 email 验证的方法,方法是使用 Firebase 的applyActionCode应用来自 URL 的actionCode

export const handleVerifyEmail = async (
  actionCode: string,
  continueUrl?: string,
  lang?: string
) => {
  try {
    await applyActionCode(auth, actionCode);
    return { alreadyVerified: false };
  } catch (err) {
    if (err instanceof FirebaseError) {
      switch (err.code) {
        case "auth/invalid-action-code": {
          return { alreadyVerified: true };
        }
      }
    }
    throw err;
  }
};

The auth/invalid-action-code error seems to be thrown when the user is already verified.当用户已经通过验证时,似乎会抛出auth/invalid-action-code错误。 I don't throw an error for it, because I handle this differently to other errors.我不会为它抛出错误,因为我处理它的方式与其他错误不同。

Once the user presses the verification link, they're redirected to the /authenticate page on my website.一旦用户按下验证链接,他们就会被重定向到我网站上的 /authenticate 页面。 This page then handles the email verification by parsing the query appended to the route.然后,此页面通过解析附加到路由的查询来处理 email 验证。 The URL looks something like this http://localhost:3000/authenticate?mode=verifyEmail&oobCode=FLVl85S-ZI13_am0uwWeb4Jy8DUWC3E6kIiwN2LLFpUAAAGDUJHSwA&apiKey=AIzaSyA_V9nKEZeoTOECWaD7UXuzqCzcptmmHQI&lang=en Of course, in production, the root path would be the name of the website instead of localhost. The URL looks something like this http://localhost:3000/authenticate?mode=verifyEmail&oobCode=FLVl85S-ZI13_am0uwWeb4Jy8DUWC3E6kIiwN2LLFpUAAAGDUJHSwA&apiKey=AIzaSyA_V9nKEZeoTOECWaD7UXuzqCzcptmmHQI&lang=en Of course, in production, the root path would be the name of the website instead of localhost. I have my development environment running on port 3000.我的开发环境在端口 3000 上运行。

Once the user lands on the authentication page, I handle the email verification in a useEffect() hook (Note: I'm using Next.js, so if you're using a different framework you might have to handle changing the URL differently):用户登陆身份验证页面后,我会在useEffect()挂钩中处理 email 验证(注意:我使用的是 Next.js,因此如果您使用不同的框架,您可能必须以不同的方式处理更改 ZE6B391A2ZD2C4D459026):

  useEffect(() => {
    verifyEmail();

    async function verifyEmail() {
      const { actionCode } = parseUrl(window.location.search);
      if (!actionCode) return;
      router.replace("/authenticate", undefined, { shallow: true });
      setLoadingState(LoadingState.LOADING);
      try {
        const response = await handleVerifyEmail(actionCode!);
        if (response.alreadyVerified) {
          setEmailAlreadyVerified(true);
          onEmailAlreadyVerified();
          return;
        }
        setLoadingState(LoadingState.SUCCESS);
        onSuccess();
      } catch (err) {
        console.error(err);
        onFailure();
        setLoadingState(LoadingState.ERROR);
      }
    }
  }, []);

It first checks if there is an action code in the URL, in case a user tries to access the page manually.它首先检查 URL 中是否有操作代码,以防用户尝试手动访问该页面。 The onSuccess , onFailure , and onEmailAlreadyVerified callbacks just display toasts. onSuccessonFailureonEmailAlreadyVerified回调仅显示 toast。 loadingState and emailAlreadyVerified are used to conditionally render different responses to the user. loadingStateemailAlreadyVerified用于有条件地向用户呈现不同的响应。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM