如何在 React-native 中从 Firebase 设置 sendSignInLinkToEmail()?

kid*_*oca 8 react-native firebase-authentication react-native-firebase

react-native使用@react-native-firebase/app v6处理一个项目,我们最近使用auth.sendSignInLinkToEmail将登录与“魔术链接”集成在一起

我们找不到关于如何在 react-native 中设置所有内容的好示例,并且遇到了不同的问题,例如 -auth/invalid-dynamic-link-domain未为当前项目配置或授权提供的动态链接域。- auth/unauthorized-continue-uri- 域未被项目列入白名单

搜索信息并实现“魔术链接登录”我准备了一份关于如何在 react-native 中进行此设置的指南

kid*_*oca 27

Firebase 项目配置

打开 Firebase 控制台

准备 firebase 实例(电子邮件链接登录)

  1. 打开验证部分。
  2. 登录方法选项卡上,启用电子邮件/密码提供程序。请注意,必须启用电子邮件/密码登录才能使用电子邮件链接登录。
  3. 在同一部分中,启用电子邮件链接(无密码登录)登录方法。
  4. 授权域选项卡上(如下所示)
  5. 添加将要使用的任何域

配置 Firebase 动态链接

  1. 对于 IOS - 您需要配置一个 ios 应用程序 - 添加一个应用程序或在整个 Firebase 控制台中指定以下内容

    • 捆绑 ID
    • 应用商店 ID
    • Apple 开发者团队 ID
  2. 对于 Android - 你只需要配置一个包名的 Android 应用程序

  3. 启用 Firebase 动态链接 - 打开动态链接部分

    • “Firebase Auth在发送要在移动应用程序中打开的链接时使用Firebase 动态链接。要使用此功能,需要在 Firebase 控制台中配置动态链接。”

(仅限 ios)您可以通过打开以下网址来验证您的 Firebase 项目是否已正确配置为在您的iOS应用中使用动态链接:https://your_dynamic_links_domain/apple-app-site-association

它应该显示如下内容:

{
     "applinks": {
         "apps": [],
         "details": [
             {
                 "appID": "AP_ID123.com.example.app",
                 "paths": [
                     "NOT /_/",                     "/"
                 ]
             }
         ]
     }
 }
Run Code Online (Sandbox Code Playgroud)

通用链接的IOS Xcode项目配置

  1. 打开 Xcode 项目并转到“信息”选项卡,创建一个用于动态链接的新 URL 类型。
  2. 标识符字段中输入唯一值,并将URL 方案字段设置为您的捆绑标识符,这是动态链接使用的默认 URL 方案。
    • 信息|网址类型设置
  3. Capabilities选项卡中,启用Associated Domains并将以下内容添加到 Associated Domains 列表中:applinks:your_dynamic_links_domain
    • (!) 这应该只是域 - 没有 https:// 前缀
    • 在此处输入图片说明

安卓

Android 不需要对默认域或自定义域进行额外配置。


套餐

需要使用 react-native-firebase 进行有效的 react-native 项目设置,这在库自己的文档中进行了详细介绍,这里是我们使用的特定包

  • 注意:使用dynamicLinks包可以替换为 react-native 自己的 Linking 模块,代码几乎相同

使用的确切包:

"@react-native-firebase/app": "^6.7.1",
"@react-native-firebase/auth": "^6.7.1",
"@react-native-firebase/dynamic-links": "^6.7.1",
Run Code Online (Sandbox Code Playgroud)

将链接发送到用户电子邮件

该模块提供了sendSignInLinkToEmail一种接受电子邮件和操作代码配置的方法。Firebase 会发送一封电子邮件,其中包含指向所提供电子邮件的魔术链接。根据操作代码配置,跟随链接有不同的行为。

下面的示例演示了如何在自己的应用程序中设置这样的流程:

EmailLinkSignIn.jsx
"@react-native-firebase/app": "^6.7.1",
"@react-native-firebase/auth": "^6.7.1",
"@react-native-firebase/dynamic-links": "^6.7.1",
Run Code Online (Sandbox Code Playgroud)

我们设置handleCodeInApptrue因为我们希望电子邮件中的链接打开我们的应用程序并在那里处理。下一节将介绍如何配置和处理此问题。

url在这种情况下,该参数是从桌面或其他未安装应用程序的设备打开链接的后备 - 它们将被重定向到提供的 url,它是必需的参数。还需要从Firebase 控制台将该 url 的域列入白名单- 身份验证 -> 登录方法

您可以在此处找到有关支持选项的更多详细信息:ActionCodeSettings

处理应用程序内的链接

需要配置原生项目,以便应用程序可以通过如上所述的通用链接启动

您可以使用内置的Linking APIreact-nativedynamicLinks @react-native-firebase/dynamic-links来拦截和处理您的应用程序内的链接

EmailLinkHandler.jsx
import React, { useState } from 'react';
import { Alert, AsyncStorage, Button, TextInput, View } from 'react-native';
import auth from '@react-native-firebase/auth';

const EmailLinkSignIn = () => {
  const [email, setEmail] = useState('');

  return (
    <View>
      <TextInput value={email} onChangeText={text => setEmail(text)} />
      <Button title="Send login link" onPress={() => sendSignInLink(email)} />
    </View>
  );
};

const BUNDLE_ID = 'com.example.ios';

const sendSignInLink = async (email) => {
  const actionCodeSettings = {
    handleCodeInApp: true,
    // URL must be whitelisted in the Firebase Console.
    url: 'https://www.example.com/magic-link',
    iOS: {
      bundleId: BUNDLE_ID,
    },
    android: {
      packageName: BUNDLE_ID,
      installApp: true,
      minimumVersion: '12',
    },
  };

  // Save the email for latter usage
  await AsyncStorage.setItem('emailForSignIn', email);

  await auth().sendSignInLinkToEmail(email, actionCodeSettings);

  Alert.alert(`Login link sent to ${email}`);
  /* You can also show a prompt to open the user's mailbox using 'react-native-email-link'
  * await openInbox({ title: `Login link sent to ${email}`, message: 'Open my mailbox' }); */
};

export default EmailLinkSignIn;
Run Code Online (Sandbox Code Playgroud)

您可以在应用程序的根目录中使用该组件,如本例所示

或者您可以将其用作单独的屏幕/路线 - 在这种情况下,用户应在sendSignInLinkToEmail操作后重定向到它

成功登录后,任何onAuthStateChanged侦听器都将使用用户的新身份验证状态触发。的结果signInWithEmailLink还可用于检索有关登录用户的信息


在模拟器中测试电子邮件登录链接

  1. 在正在运行的模拟器上安装应用程序
  2. 完成将魔术链接发送到电子邮件的流程
  3. 转到您的收件箱并复制链接地址
  4. 打开终端并粘贴以下代码
import React, { useState, useEffect } from 'react';
import { ActivityIndicator, AsyncStorage, StyleSheet, Text, View } from 'react-native';
import auth from '@react-native-firebase/auth';
import dynamicLinks from '@react-native-firebase/dynamic-links';

const EmailLinkHandler = () => {
  const { loading, error } = useEmailLinkEffect();

  // Show an overlay with a loading indicator while the email link is processed
  if (loading || error) {
     return (
      <View style={styles.container}>
        {Boolean(error) && <Text>{error.message}</Text>}
        {loading && <ActivityIndicator />}
      </View>
    );
  }

  // Hide otherwise. Or show some content if you are using this as a separate screen
  return null;
};

const useEmailLinkEffect = () => {
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState(null);

  useEffect(() => {
    const handleDynamicLink = async (link) => {
      // Check and handle if the link is a email login link
      if (auth().isSignInWithEmailLink(link.url)) {
        setLoading(true);

        try {
          // use the email we saved earlier
          const email = await AsyncStorage.getItem('emailForSignIn');
          await auth().signInWithEmailLink(email, link.url);

          /* You can now navigate to your initial authenticated screen
            You can also parse the `link.url` and use the `continueurl` param to go to another screen
            The `continueurl` would be the `url` passed to the action code settings */
        }
        catch (e) {
          setError(e);
        }
        finally {
          setLoading(false);
        }
      }
    };

    const unsubscribe = dynamicLinks().onLink(handleDynamicLink);

     /* When the app is not running and is launched by a magic link the `onLink`
        method won't fire, we can handle the app being launched by a magic link like this */
    dynamicLinks().getInitialLink()
      .then(link => link && handleDynamicLink(link));

    // When the component is unmounted, remove the listener
    return () => unsubscribe();
  }, []);

  return { error, loading };
};

const styles = StyleSheet.create({
  container: {
    ...StyleSheet.absoluteFill,
    backgroundColor: 'rgba(250,250,250,0.33)',
    justifyContent: 'center',
    alignItems: 'center',
  },
});

const App = () => (
  <View>
    <EmailLinkHandler />
    <AppScreens />
  </View>
);
Run Code Online (Sandbox Code Playgroud)
  • 如果它没有运行,这将启动应用程序
  • 它会触发 onLink 钩子(如果你有一个像上面那样的监听器)

参考