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

يمكنك استخدام Firebase Authentication لتسجيل دخول مستخدم من خلال إرسال رسالة إلكترونية إليه تتضمّن رابطًا يمكنه النقر عليه لتسجيل الدخول. وخلال هذه العملية، يتم أيضًا إثبات ملكية عنوان البريد الإلكتروني للمستخدم.

هناك العديد من المزايا لتسجيل الدخول باستخدام عنوان البريد الإلكتروني:

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

قبل البدء

إعداد مشروع Android

  1. أضِف Firebase إلى مشروع Android الخاص بك، في حال لم يسبق لك إجراء ذلك.

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

    بالإضافة إلى ذلك، كجزء من إعداد Firebase Authentication، عليك إضافة حزمة تطوير البرامج (SDK) لـ "خدمات Google Play" إلى تطبيقك.

    dependencies {
        // Import the BoM for the Firebase platform
        implementation(platform("com.google.firebase:firebase-bom:33.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.3.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:23.1.0")
    // Also add the dependency for the Google Play services library and specify its version implementation("com.google.android.gms:play-services-auth:21.3.0")
    }
    هل تبحث عن وحدة مكتبة خاصة بلغة Kotlin؟ اعتبارًا من تشرين الأول (أكتوبر) 2023 (Firebase BoM 32.5.0)، يمكن لمطوّري Kotlin وJava الاعتماد على وحدة المكتبة الرئيسية (للاطّلاع على التفاصيل، راجِع الأسئلة الشائعة حول هذه المبادرة).

تفعيل ميزة تسجيل الدخول باستخدام رابط البريد الإلكتروني لمشروعك على Firebase

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

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

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

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

    • url: الرابط لصفحة في التطبيق المطلوب تضمينه وأي حالة إضافية المطلوب تمريرها يجب أن يكون نطاق الرابط مُدرَجًا في القائمة المسموح بها في "وحدة تحكّم Firebase" للنطاقات المعتمَدة، والتي يمكن العثور عليها من خلال الانتقال إلى علامة التبويب "طريقة تسجيل الدخول" (المصادقة -> طريقة تسجيل الدخول). سيعيد الرابط توجيه المستخدم إلى عنوان URL هذا إذا لم يكن التطبيق مثبّتًا على جهازه ولم يكن بإمكانه تثبيته.
    • androidPackageName وiOSBundleId: تساعدان Firebase Authentication في تحديد ما إذا كان يجب إنشاء رابط مخصّص للويب فقط أو للأجهزة الجوّالة يتم فتحه على جهاز Android أو Apple.
    • handleCodeInApp: يتم ضبطها على true. يجب إكمال عملية تسجيل الدخول دائمًا في التطبيق على عكس الإجراءات الأخرى التي تتم خارج نطاق البريد الإلكتروني (مثل إعادة ضبط كلمة المرور وإثبات ملكية البريد الإلكتروني). ويعود السبب في ذلك إلى أنّه في نهاية العملية، من المتوقّع أن يكون المستخدم مسجِّلاً الدخول وأن تظل حالة المصادقة محفوظة في التطبيق.
    • linkDomain: عند تحديد نطاقات روابط Hosting مخصّصة لمشروع، حدِّد النطاق الذي تريد استخدامه عند فتح الرابط من خلال تطبيق جوّال محدّد. بخلاف ذلك، يتم تحديد النطاق التلقائي تلقائيًا (على سبيل المثال، PROJECT_ID.firebaseapp.com).
    • dynamicLinkDomain: تم إيقاف هذا العمود نهائيًا. لا تحدّد هذه المَعلمة.

    Kotlin

    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

    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 Authentication تقديم عنوان البريد الإلكتروني للمستخدم عند إكمال عملية تسجيل الدخول. لكي تنجح عملية تسجيل الدخول، يجب أن يتطابق عنوان البريد الإلكتروني هذا مع العنوان الذي تم إرسال رابط تسجيل الدخول إليه في الأصل.

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

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

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

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

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

ضبط Firebase Hosting

يستخدم Firebase Authentication نطاقات Firebase Hosting عند إنشاء رابط وإرساله يُفترض فتحه في تطبيق على الأجهزة الجوّالة. سبق أن تم إعداد نطاق Firebase Hosting تلقائي لك.

  1. ضبط Firebase Hosting نطاق:

    في وحدة تحكّم Firebase، افتح القسم استضافة.

    • إذا كنت تريد استخدام النطاق التلقائي لرابط البريد الإلكتروني الذي يتم فتحه في التطبيقات المتوافقة مع الأجهزة الجوّالة، انتقِل إلى موقعك الإلكتروني التلقائي وسجِّل النطاق التلقائي Hosting. يظهر نطاق Hosting التلقائي عادةً على النحو التالي: PROJECT_ID.firebaseapp.com.

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

    • إذا كنت تريد استخدام نطاق مخصّص لرابط البريد الإلكتروني، يمكنك تسجيل نطاق باستخدام Firebase Hosting واستخدامه لنطاق الرابط.

  2. ضبط تطبيقات Android:

    لمعالجة هذه الروابط من تطبيق Android، يجب تحديد اسم حزمة تطبيقك في إعدادات مشروع Firebase console. بالإضافة إلى ذلك، يجب تقديم SHA-1 وSHA-256 لشهادة التطبيق.

    إذا كنت تريد إعادة توجيه هذه الروابط إلى نشاط معيّن، عليك ضبط فلتر أهداف في ملف AndroidManifest.xml. من المفترض أن يرصد فلتر القصْد روابط البريد الإلكتروني لنطاقك. في AndroidManifest.xml:

    <intent-filter android:autoVerify="true">
      <action android:name="android.intent.action.VIEW" />
      <category android:name="android.intent.category.BROWSABLE" />
      <category android:name="android.intent.category.DEFAULT" />
      <data
        android:scheme="https"
        android:host="<PROJECT_ID>.firebaseapp.com or your custom domain"
        android:pathPrefix="/__/auth/links" />
    </intent-filter>
    

    عندما يفتح المستخدمون رابط استضافة يتضمّن المسار /__/auth/links والمخطّط والمضيف الذي تحدّده، سيبدأ تطبيقك النشاط باستخدام فلتر القصد هذا لمعالجة الرابط.

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

Kotlin

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

// 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

// 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());
                }
            }
        });

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

كانت مصادقة رابط البريد الإلكتروني تعتمد في السابق على Firebase Dynamic Links، الذي سيتم إيقافه نهائيًا في 25 آب (أغسطس) 2025.

لقد نشرنا حلًا بديلاً في حزمة تطوير البرامج (SDK) لنظام التشغيل Firebase Authentication Android الإصدار 23.2.0 والإصدارات الأحدث وFirebase BoM الإصدار 33.9.0 والإصدارات الأحدث.

إذا كان تطبيقك يستخدم الروابط القديمة، عليك نقل بيانات تطبيقك إلى النظام الجديد المستنِد إلىFirebase Hosting.

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

على الرغم من أنّه يمكنك إيقاف ميزة "حماية تعداد عناوين البريد الإلكتروني" لمشروعك، ننصحك بعدم إجراء ذلك.

اطّلِع على المستندات حول حماية تعداد عناوين البريد الإلكتروني لمزيد من التفاصيل.

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

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

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

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

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

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

Kotlin

Firebase.auth.signOut()

Java

FirebaseAuth.getInstance().signOut();