قم بالمصادقة مع Firebase باستخدام رابط البريد الإلكتروني في Android

يمكنك استخدام مصادقة Firebase لتسجيل الدخول إلى مستخدم عن طريق إرسال بريد إلكتروني إليه يحتوي على رابط، والذي يمكنه النقر عليه لتسجيل الدخول. وفي هذه العملية، يتم أيضًا التحقق من عنوان البريد الإلكتروني للمستخدم.

هناك فوائد عديدة لتسجيل الدخول عبر البريد الإلكتروني:

  • انخفاض الاحتكاك في الاشتراك وتسجيل الدخول.
  • انخفاض خطر إعادة استخدام كلمة المرور عبر التطبيقات، الأمر الذي يمكن أن يقوض أمان حتى كلمات المرور المحددة جيدًا.
  • القدرة على مصادقة المستخدم مع التحقق أيضًا من أن المستخدم هو المالك الشرعي لعنوان البريد الإلكتروني.
  • يحتاج المستخدم فقط إلى حساب بريد إلكتروني يمكن الوصول إليه لتسجيل الدخول. ولا يلزم ملكية رقم هاتف أو حساب على وسائل التواصل الاجتماعي.
  • يمكن للمستخدم تسجيل الدخول بشكل آمن دون الحاجة إلى توفير (أو تذكر) كلمة مرور، الأمر الذي قد يكون مرهقًا على جهاز محمول.
  • يمكن ترقية المستخدم الحالي الذي قام بتسجيل الدخول مسبقًا باستخدام معرف البريد الإلكتروني (كلمة المرور أو المتحد) لتسجيل الدخول باستخدام البريد الإلكتروني فقط. على سبيل المثال، لا يزال بإمكان المستخدم الذي نسي كلمة المرور الخاصة به تسجيل الدخول دون الحاجة إلى إعادة تعيين كلمة المرور الخاصة به.

قبل ان تبدأ

قم بإعداد مشروع Android الخاص بك

  1. إذا لم تكن قد قمت بذلك بالفعل، فأضف Firebase إلى مشروع Android الخاص بك .

  2. في ملف Gradle الخاص بالوحدة النمطية (على مستوى التطبيق) (عادةً <project>/<app-module>/build.gradle.kts أو <project>/<app-module>/build.gradle )، أضف التبعية لمصادقة Firebase مكتبة لالروبوت. نوصي باستخدام Firebase Android BoM للتحكم في إصدار المكتبة.

    وأيضًا، كجزء من إعداد مصادقة Firebase، تحتاج إلى إضافة SDK لخدمات Google Play إلى تطبيقك.

    dependencies {
        // Import the BoM for the Firebase platform
        implementation(platform("com.google.firebase:firebase-bom:32.8.0"))
    
        // Add the dependency for the Firebase Authentication library
        // When using the BoM, you don't specify versions in Firebase library dependencies
        implementation("com.google.firebase:firebase-auth")
    // Also add the dependency for the Google Play services library and specify its version implementation("com.google.android.gms:play-services-auth:21.0.0")
    }

    باستخدام Firebase Android BoM ، سيستخدم تطبيقك دائمًا إصدارات متوافقة من مكتبات Firebase Android.

    (بديل) أضف تبعيات مكتبة Firebase دون استخدام BoM

    إذا اخترت عدم استخدام Firebase BoM، فيجب عليك تحديد كل إصدار من مكتبة Firebase في سطر التبعية الخاص به.

    لاحظ أنه إذا كنت تستخدم مكتبات Firebase متعددة في تطبيقك، فإننا نوصي بشدة باستخدام BoM لإدارة إصدارات المكتبة، مما يضمن توافق جميع الإصدارات.

    dependencies {
        // Add the dependency for the Firebase Authentication library
        // When NOT using the BoM, you must specify versions in Firebase library dependencies
        implementation("com.google.firebase:firebase-auth:22.3.1")
    // Also add the dependency for the Google Play services library and specify its version implementation("com.google.android.gms:play-services-auth:21.0.0")
    }
    هل تبحث عن وحدة مكتبة خاصة بـ Kotlin؟ بدءًا من أكتوبر 2023 (Firebase BoM 32.5.0) ، يمكن لمطوري Kotlin وJava الاعتماد على وحدة المكتبة الرئيسية (لمزيد من التفاصيل، راجع الأسئلة الشائعة حول هذه المبادرة ).

لتسجيل دخول المستخدمين عن طريق رابط البريد الإلكتروني، يجب عليك أولاً تمكين موفر البريد الإلكتروني وطريقة تسجيل الدخول برابط البريد الإلكتروني لمشروع Firebase الخاص بك:

  1. في وحدة تحكم Firebase ، افتح قسم المصادقة .
  2. في علامة التبويب طريقة تسجيل الدخول ، قم بتمكين موفر البريد الإلكتروني/كلمة المرور . لاحظ أنه يجب تمكين تسجيل الدخول عبر البريد الإلكتروني/كلمة المرور لاستخدام تسجيل الدخول عبر رابط البريد الإلكتروني.
  3. في نفس القسم، قم بتمكين طريقة تسجيل الدخول عبر رابط البريد الإلكتروني (تسجيل الدخول بدون كلمة مرور) .
  4. انقر فوق حفظ .

لبدء تدفق المصادقة، قدم للمستخدم واجهة تطالب المستخدم بتقديم عنوان بريده الإلكتروني ثم اتصل بـ sendSignInLinkToEmail لمطالبة Firebase بإرسال رابط المصادقة إلى البريد الإلكتروني للمستخدم.

  1. أنشئ كائن ActionCodeSettings ، الذي يزود Firebase بتعليمات حول كيفية إنشاء رابط البريد الإلكتروني. قم بتعيين الحقول التالية:

    • url : الرابط العميق المراد تضمينه وأي حالة إضافية سيتم تمريرها. يجب إدراج نطاق الرابط في القائمة البيضاء في قائمة Firebase Console للنطاقات المعتمدة، والتي يمكن العثور عليها بالانتقال إلى علامة تبويب طريقة تسجيل الدخول (المصادقة -> طريقة تسجيل الدخول). سيعيد الرابط توجيه المستخدم إلى عنوان URL هذا إذا لم يكن التطبيق مثبتًا على أجهزته ولم يكن من الممكن تثبيت التطبيق.
    • androidPackageName و IOSBundleId : التطبيقات التي يتم استخدامها عند فتح رابط تسجيل الدخول على جهاز Android أو Apple. تعرف على المزيد حول كيفية تكوين روابط Firebase الديناميكية لفتح روابط إجراءات البريد الإلكتروني عبر تطبيقات الهاتف المحمول.
    • handleCodeInApp : اضبط على true. يجب أن تكتمل عملية تسجيل الدخول دائمًا في التطبيق بخلاف إجراءات البريد الإلكتروني الأخرى خارج النطاق (إعادة تعيين كلمة المرور والتحقق من البريد الإلكتروني). وذلك لأنه، في نهاية التدفق، من المتوقع أن يقوم المستخدم بتسجيل الدخول وأن تستمر حالة المصادقة الخاصة به داخل التطبيق.
    • dynamicLinkDomain : عند تحديد مجالات ارتباط ديناميكي مخصصة متعددة لمشروع ما، حدد النطاق الذي سيتم استخدامه عند فتح الرابط عبر تطبيق جوال محدد (على سبيل المثال، example.page.link ). وإلا فسيتم تحديد النطاق الأول تلقائيًا.

    Kotlin+KTX

    val actionCodeSettings = actionCodeSettings {
        // URL you want to redirect back to. The domain (www.example.com) for this
        // URL must be whitelisted in the Firebase Console.
        url = "https://www.example.com/finishSignUp?cartId=1234"
        // This must be true
        handleCodeInApp = true
        setIOSBundleId("com.example.ios")
        setAndroidPackageName(
            "com.example.android",
            true, // installIfNotAvailable
            "12", // minimumVersion
        )
    }

    Java

    ActionCodeSettings actionCodeSettings =
            ActionCodeSettings.newBuilder()
                    // URL you want to redirect back to. The domain (www.example.com) for this
                    // URL must be whitelisted in the Firebase Console.
                    .setUrl("https://www.example.com/finishSignUp?cartId=1234")
                    // This must be true
                    .setHandleCodeInApp(true)
                    .setIOSBundleId("com.example.ios")
                    .setAndroidPackageName(
                            "com.example.android",
                            true, /* installIfNotAvailable */
                            "12"    /* minimumVersion */)
                    .build();

    لمعرفة المزيد حول ActionCodeSettings، راجع حالة المرور في قسم إجراءات البريد الإلكتروني .

  2. اطلب من المستخدم بريده الإلكتروني.

  3. أرسل رابط المصادقة إلى البريد الإلكتروني للمستخدم، واحفظ البريد الإلكتروني للمستخدم في حالة قيام المستخدم بإكمال تسجيل الدخول عبر البريد الإلكتروني على نفس الجهاز.

    Kotlin+KTX

    Firebase.auth.sendSignInLinkToEmail(email, actionCodeSettings)
        .addOnCompleteListener { task ->
            if (task.isSuccessful) {
                Log.d(TAG, "Email sent.")
            }
        }

    Java

    FirebaseAuth auth = FirebaseAuth.getInstance();
    auth.sendSignInLinkToEmail(email, actionCodeSettings)
            .addOnCompleteListener(new OnCompleteListener<Void>() {
                @Override
                public void onComplete(@NonNull Task<Void> task) {
                    if (task.isSuccessful()) {
                        Log.d(TAG, "Email sent.");
                    }
                }
            });

مخاوف أمنية

لمنع استخدام رابط تسجيل الدخول لتسجيل الدخول كمستخدم غير مقصود أو على جهاز غير مقصود، تتطلب Firebase Auth تقديم عنوان البريد الإلكتروني للمستخدم عند إكمال تدفق تسجيل الدخول. لكي تنجح عملية تسجيل الدخول، يجب أن يتطابق عنوان البريد الإلكتروني هذا مع العنوان الذي تم إرسال رابط تسجيل الدخول إليه في الأصل.

يمكنك تبسيط هذا التدفق للمستخدمين الذين يفتحون رابط تسجيل الدخول على نفس الجهاز الذي يطلبون فيه الارتباط، عن طريق تخزين عنوان بريدهم الإلكتروني محليًا - على سبيل المثال باستخدام SharedPreferences - عندما ترسل بريدًا إلكترونيًا لتسجيل الدخول. ثم استخدم هذا العنوان لإكمال التدفق. لا تمرر البريد الإلكتروني للمستخدم في معلمات عنوان URL لإعادة التوجيه وأعد استخدامه لأن ذلك قد يؤدي إلى تمكين عمليات حقن الجلسة.

بعد اكتمال تسجيل الدخول، ستتم إزالة أي آلية تسجيل دخول سابقة لم يتم التحقق منها من المستخدم وسيتم إبطال أي جلسات موجودة. على سبيل المثال، إذا قام شخص ما مسبقًا بإنشاء حساب لم يتم التحقق منه باستخدام نفس البريد الإلكتروني وكلمة المرور، فستتم إزالة كلمة مرور المستخدم لمنع المنتحل الذي ادعى الملكية وأنشأ هذا الحساب الذي لم يتم التحقق منه من تسجيل الدخول مرة أخرى باستخدام البريد الإلكتروني وكلمة المرور التي لم يتم التحقق منها.

تأكد أيضًا من استخدام عنوان URL HTTPS في الإنتاج لتجنب احتمال اعتراض الارتباط الخاص بك بواسطة الخوادم الوسيطة.

إكمال تسجيل الدخول في تطبيق Android

تستخدم مصادقة Firebase روابط Firebase الديناميكية لإرسال رابط البريد الإلكتروني إلى جهاز محمول. لإكمال تسجيل الدخول عبر تطبيق الهاتف المحمول، يجب تكوين التطبيق لاكتشاف رابط التطبيق الوارد، وتحليل الرابط العميق الأساسي ثم إكمال تسجيل الدخول.

يستخدم Firebase Auth روابط Firebase الديناميكية عند إرسال رابط يُقصد فتحه في تطبيق الهاتف المحمول. لاستخدام هذه الميزة، يجب تهيئة الروابط الديناميكية في وحدة تحكم Firebase.

  1. تمكين الروابط الديناميكية لـ Firebase:

    1. في وحدة تحكم Firebase ، افتح قسم الروابط الديناميكية .
    2. إذا لم تكن قد قبلت شروط الارتباطات الديناميكية بعد وقمت بإنشاء مجال الارتباطات الديناميكية، فقم بذلك الآن.

      إذا قمت بالفعل بإنشاء مجال الارتباطات الديناميكية، فلاحظ ذلك. عادةً ما يبدو مجال الارتباطات الديناميكية كالمثال التالي:

      example.page.link

      ستحتاج إلى هذه القيمة عند تكوين تطبيق Apple أو Android الخاص بك لاعتراض الرابط الوارد.

  2. تكوين تطبيقات أندرويد:

    1. للتعامل مع هذه الروابط من تطبيق Android الخاص بك، يجب تحديد اسم حزمة Android في إعدادات مشروع Firebase Console. بالإضافة إلى ذلك، يجب تقديم SHA-1 وSHA-256 لشهادة الطلب.
    2. الآن بعد أن قمت بإضافة مجال رابط ديناميكي وتأكدت من تكوين تطبيق Android الخاص بك بشكل صحيح، سيتم إعادة توجيه الرابط الديناميكي إلى تطبيقك، بدءًا من نشاط المشغل.
    3. إذا كنت تريد إعادة توجيه الرابط الديناميكي إلى نشاط معين، فستحتاج إلى تكوين مرشح الغرض في ملف AndroidManifest.xml الخاص بك. يمكن القيام بذلك إما عن طريق تحديد مجال الارتباط الديناميكي الخاص بك أو معالج إجراء البريد الإلكتروني في مرشح النوايا. افتراضيًا، تتم استضافة معالج إجراء البريد الإلكتروني على مجال مثل المثال التالي:
      PROJECT_ID.firebaseapp.com/
    4. تحفظات:
      1. لا تحدد عنوان URL الذي قمت بتعيينه في actionCodeSettings في مرشح النوايا الخاص بك.
      2. عند إنشاء مجال الارتباط الديناميكي الخاص بك، ربما تكون قد قمت أيضًا بإنشاء رابط URL قصير. لن يتم تمرير عنوان URL القصير هذا؛ لا تقم بتكوين مرشح النوايا الخاص بك لالتقاطه باستخدام سمة android:pathPrefix . وهذا يعني أنك لن تتمكن من التقاط روابط ديناميكية مختلفة في أجزاء مختلفة من تطبيقك. ومع ذلك، يمكنك التحقق من معلمة استعلام mode في الرابط لمعرفة العملية التي يحاول تنفيذها، أو استخدام أساليب SDK مثل isSignInWithEmailLink لمعرفة ما إذا كان الرابط الذي تلقاه تطبيقك يفعل ما تريد.
    5. لمعرفة المزيد حول تلقي الروابط الديناميكية، راجع تعليمات تلقي الروابط الديناميكية لنظام Android .

بعد أن تتلقى الرابط كما هو موضح أعلاه، تأكد من أنه مخصص لمصادقة رابط البريد الإلكتروني وأكمل تسجيل الدخول.

Kotlin+KTX

val auth = Firebase.auth
val intent = intent
val emailLink = intent.data.toString()

// Confirm the link is a sign-in with email link.
if (auth.isSignInWithEmailLink(emailLink)) {
    // Retrieve this from wherever you stored it
    val email = "someemail@domain.com"

    // The client SDK will parse the code from the link for you.
    auth.signInWithEmailLink(email, emailLink)
        .addOnCompleteListener { task ->
            if (task.isSuccessful) {
                Log.d(TAG, "Successfully signed in with email link!")
                val result = task.result
                // You can access the new user via result.getUser()
                // Additional user info profile *not* available via:
                // result.getAdditionalUserInfo().getProfile() == null
                // You can check if the user is new or existing:
                // result.getAdditionalUserInfo().isNewUser()
            } else {
                Log.e(TAG, "Error signing in with email link", task.exception)
            }
        }
}

Java

FirebaseAuth auth = FirebaseAuth.getInstance();
Intent intent = getIntent();
String emailLink = intent.getData().toString();

// Confirm the link is a sign-in with email link.
if (auth.isSignInWithEmailLink(emailLink)) {
    // Retrieve this from wherever you stored it
    String email = "someemail@domain.com";

    // The client SDK will parse the code from the link for you.
    auth.signInWithEmailLink(email, emailLink)
            .addOnCompleteListener(new OnCompleteListener<AuthResult>() {
                @Override
                public void onComplete(@NonNull Task<AuthResult> task) {
                    if (task.isSuccessful()) {
                        Log.d(TAG, "Successfully signed in with email link!");
                        AuthResult result = task.getResult();
                        // You can access the new user via result.getUser()
                        // Additional user info profile *not* available via:
                        // result.getAdditionalUserInfo().getProfile() == null
                        // You can check if the user is new or existing:
                        // result.getAdditionalUserInfo().isNewUser()
                    } else {
                        Log.e(TAG, "Error signing in with email link", task.getException());
                    }
                }
            });
}

لمعرفة المزيد حول كيفية التعامل مع تسجيل الدخول باستخدام رابط البريد الإلكتروني في أحد تطبيقات Apple، راجع دليل منصات Apple .

للتعرف على كيفية التعامل مع تسجيل الدخول باستخدام رابط البريد الإلكتروني في تطبيق ويب، راجع دليل الويب .

يمكنك أيضًا ربط طريقة المصادقة هذه بمستخدم حالي. على سبيل المثال، يمكن للمستخدم الذي تمت مصادقته مسبقًا مع موفر آخر، مثل رقم الهاتف، إضافة طريقة تسجيل الدخول هذه إلى حسابه الحالي.

سيكون الفرق في النصف الثاني من العملية:

Kotlin+KTX

// Construct the email link credential from the current URL.
val credential = EmailAuthProvider.getCredentialWithLink(email, emailLink)

// Link the credential to the current user.
Firebase.auth.currentUser!!.linkWithCredential(credential)
    .addOnCompleteListener { task ->
        if (task.isSuccessful) {
            Log.d(TAG, "Successfully linked emailLink credential!")
            val result = task.result
            // You can access the new user via result.getUser()
            // Additional user info profile *not* available via:
            // result.getAdditionalUserInfo().getProfile() == null
            // You can check if the user is new or existing:
            // result.getAdditionalUserInfo().isNewUser()
        } else {
            Log.e(TAG, "Error linking emailLink credential", task.exception)
        }
    }

Java

// Construct the email link credential from the current URL.
AuthCredential credential =
        EmailAuthProvider.getCredentialWithLink(email, emailLink);

// Link the credential to the current user.
auth.getCurrentUser().linkWithCredential(credential)
        .addOnCompleteListener(new OnCompleteListener<AuthResult>() {
            @Override
            public void onComplete(@NonNull Task<AuthResult> task) {
                if (task.isSuccessful()) {
                    Log.d(TAG, "Successfully linked emailLink credential!");
                    AuthResult result = task.getResult();
                    // You can access the new user via result.getUser()
                    // Additional user info profile *not* available via:
                    // result.getAdditionalUserInfo().getProfile() == null
                    // You can check if the user is new or existing:
                    // result.getAdditionalUserInfo().isNewUser()
                } else {
                    Log.e(TAG, "Error linking emailLink credential", task.getException());
                }
            }
        });

يمكن أيضًا استخدام هذا لإعادة مصادقة مستخدم رابط البريد الإلكتروني قبل تشغيل عملية حساسة.

Kotlin+KTX

// Construct the email link credential from the current URL.
val credential = EmailAuthProvider.getCredentialWithLink(email, emailLink)

// Re-authenticate the user with this credential.
Firebase.auth.currentUser!!.reauthenticateAndRetrieveData(credential)
    .addOnCompleteListener { task ->
        if (task.isSuccessful) {
            // User is now successfully reauthenticated
        } else {
            Log.e(TAG, "Error reauthenticating", task.exception)
        }
    }

Java

// Construct the email link credential from the current URL.
AuthCredential credential =
        EmailAuthProvider.getCredentialWithLink(email, emailLink);

// Re-authenticate the user with this credential.
auth.getCurrentUser().reauthenticateAndRetrieveData(credential)
        .addOnCompleteListener(new OnCompleteListener<AuthResult>() {
            @Override
            public void onComplete(@NonNull Task<AuthResult> task) {
                if (task.isSuccessful()) {
                    // User is now successfully reauthenticated
                } else {
                    Log.e(TAG, "Error reauthenticating", task.getException());
                }
            }
        });

ومع ذلك، بما أن التدفق قد ينتهي على جهاز مختلف حيث لم يتم تسجيل دخول المستخدم الأصلي، فقد لا يكتمل هذا التدفق. وفي هذه الحالة، يمكن أن يظهر خطأ للمستخدم لإجباره على فتح الرابط على نفس الجهاز. يمكن تمرير بعض الحالات في الرابط لتوفير معلومات حول نوع العملية ومعرف المستخدم.

إذا قمت بإنشاء مشروعك في 15 سبتمبر 2023 أو بعده، فسيتم تمكين حماية تعداد البريد الإلكتروني بشكل افتراضي. تعمل هذه الميزة على تحسين أمان حسابات المستخدمين الخاصة بمشروعك، ولكنها تعمل على تعطيل طريقة fetchSignInMethodsForEmail() ، والتي أوصينا بها سابقًا لتنفيذ تدفقات المعرف أولاً.

على الرغم من أنه يمكنك تعطيل حماية تعداد البريد الإلكتروني لمشروعك، إلا أننا نوصي بعدم القيام بذلك.

راجع الوثائق الخاصة بحماية تعداد البريد الإلكتروني لمزيد من التفاصيل.

الخطوات التالية

بعد قيام المستخدم بتسجيل الدخول لأول مرة، يتم إنشاء حساب مستخدم جديد وربطه ببيانات الاعتماد - أي اسم المستخدم وكلمة المرور أو رقم الهاتف أو معلومات موفر المصادقة - التي قام المستخدم بتسجيل الدخول بها. يتم تخزين هذا الحساب الجديد كجزء من مشروع Firebase الخاص بك، ويمكن استخدامه لتحديد المستخدم عبر كل تطبيق في مشروعك، بغض النظر عن كيفية تسجيل دخول المستخدم.

  • في تطبيقاتك، يمكنك الحصول على معلومات الملف الشخصي الأساسية للمستخدم من كائن FirebaseUser . راجع إدارة المستخدمين .

  • في قاعدة بيانات Firebase Realtime وقواعد أمان التخزين السحابي، يمكنك الحصول على معرف المستخدم الفريد للمستخدم الذي قام بتسجيل الدخول من متغير auth ، واستخدامه للتحكم في البيانات التي يمكن للمستخدم الوصول إليها.

يمكنك السماح للمستخدمين بتسجيل الدخول إلى تطبيقك باستخدام موفري مصادقة متعددين عن طريق ربط بيانات اعتماد موفر المصادقة بحساب مستخدم موجود.

لتسجيل خروج مستخدم، اتصل signOut :

Kotlin+KTX

Firebase.auth.signOut()

Java

FirebaseAuth.getInstance().signOut();