با Firebase با استفاده از Email Link در اندروید احراز هویت

می‌توانید از Firebase Authentication برای ورود به سیستم استفاده کنید و با ارسال یک ایمیل حاوی یک پیوند به او، کاربر می‌تواند روی آن کلیک کند تا وارد شود. در این فرآیند، آدرس ایمیل کاربر نیز تأیید می‌شود.

ورود از طریق ایمیل مزایای زیادی دارد:

  • ثبت نام و ورود به سیستم با اصطکاک کم.
  • خطر کمتر استفاده مجدد از رمز عبور در بین برنامه‌ها، که می‌تواند امنیت رمزهای عبور انتخاب شده را نیز تضعیف کند.
  • امکان احراز هویت یک کاربر و همچنین تأیید اینکه کاربر مالک قانونی آدرس ایمیل است.
  • یک کاربر برای ورود فقط به یک حساب ایمیل قابل دسترسی نیاز دارد. مالکیت شماره تلفن یا حساب رسانه اجتماعی مورد نیاز نیست.
  • یک کاربر می تواند بدون نیاز به ارائه (یا به خاطر سپردن) رمز عبور، به طور ایمن وارد سیستم شود، که ممکن است در یک دستگاه تلفن همراه دست و پا گیر باشد.
  • کاربر موجودی که قبلاً با یک شناسه ایمیل (رمز عبور یا فدرال) وارد شده است را می توان ارتقا داد تا فقط با ایمیل وارد شود. به عنوان مثال، کاربری که رمز عبور خود را فراموش کرده است همچنان می تواند بدون نیاز به بازنشانی رمز عبور خود وارد سیستم شود.

قبل از شروع

پروژه اندروید خود را راه اندازی کنید

  1. اگر قبلاً این کار را نکرده‌اید، Firebase را به پروژه Android خود اضافه کنید .

  2. در فایل Gradle ماژول (سطح برنامه) خود (معمولا <project>/<app-module>/build.gradle.kts یا <project>/<app-module>/build.gradle )، وابستگی را برای Firebase Authentication اضافه کنید. کتابخانه برای اندروید توصیه می‌کنیم از Firebase Android BoM برای کنترل نسخه‌سازی کتابخانه استفاده کنید.

    همچنین، به عنوان بخشی از راه‌اندازی Firebase Authentication ، باید SDK خدمات Google Play را به برنامه خود اضافه کنید.

    dependencies {
        // Import the BoM for the Firebase platform
        implementation(platform("com.google.firebase:firebase-bom:33.3.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.2.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.0.0")
    // Also add the dependency for the Google Play services library and specify its version implementation("com.google.android.gms:play-services-auth:21.2.0")
    }
    به دنبال یک ماژول کتابخانه خاص کاتلین هستید؟ از اکتبر 2023 ( Firebase BoM 32.5.0) ، توسعه دهندگان Kotlin و Java می توانند به ماژول کتابخانه اصلی وابسته باشند (برای جزئیات، به سؤالات متداول در مورد این ابتکار مراجعه کنید).

برای ورود کاربران از طریق پیوند ایمیل، ابتدا باید روش ورود ارائه دهنده ایمیل و پیوند ایمیل را برای پروژه Firebase خود فعال کنید:

  1. در کنسول Firebase ، بخش Auth را باز کنید.
  2. در برگه روش ورود به سیستم ، ارائه دهنده ایمیل/گذرواژه را فعال کنید. توجه داشته باشید که ورود ایمیل/رمز عبور برای استفاده از ورود به سیستم پیوند ایمیل باید فعال باشد.
  3. در همان بخش، روش ورود به سیستم پیوند ایمیل (ورود بدون رمز عبور) را فعال کنید.
  4. روی ذخیره کلیک کنید.

برای شروع جریان احراز هویت، رابطی را به کاربر ارائه دهید که از کاربر می‌خواهد آدرس ایمیل خود را ارائه کند و سپس sendSignInLinkToEmail را فراخوانی کنید تا از Firebase درخواست کنید که پیوند احراز هویت را به ایمیل کاربر ارسال کند.

  1. شی ActionCodeSettings را بسازید، که دستورالعمل‌هایی را در مورد نحوه ساخت پیوند ایمیل به Firebase ارائه می‌دهد. فیلدهای زیر را تنظیم کنید:

    • url : پیوند عمیق برای جاسازی و هر حالت اضافی که باید همراه آن منتقل شود. دامنه پیوند باید در لیست دامنه های مجاز Firebase Console قرار گیرد که با رفتن به برگه روش ورود (Authentication -> Sign-in) می توانید آن را پیدا کنید. اگر برنامه روی دستگاهش نصب نشده باشد و برنامه نصب نشود، پیوند کاربر را به این URL هدایت می‌کند.
    • androidPackageName و IOSBundleId : برنامه‌هایی که هنگام باز شدن پیوند ورود به سیستم در دستگاه Android یا Apple استفاده می‌شوند. درباره نحوه پیکربندی Firebase Dynamic Links برای باز کردن پیوندهای اقدام ایمیل از طریق برنامه های تلفن همراه بیشتر بیاموزید.
    • handleCodeInApp : روی true تنظیم کنید. عملیات ورود به سیستم برخلاف سایر اقدامات ایمیل خارج از باند (بازنشانی رمز عبور و تأیید ایمیل) باید همیشه در برنامه تکمیل شود. این به این دلیل است که در پایان جریان، انتظار می رود کاربر وارد سیستم شود و وضعیت Auth او در برنامه باقی بماند.
    • 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، به بخش Passing State in Email Actions مراجعه کنید.

  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 Dynamic Links استفاده می کند. برای استفاده از این ویژگی، Dynamic Links باید در کنسول Firebase پیکربندی شود.

  1. فعال کردن Firebase Dynamic Links:

    1. در کنسول Firebase ، بخش Dynamic Links را باز کنید.
    2. اگر هنوز شرایط Dynamic Links را نپذیرفته اید و دامنه Dynamic Links ایجاد نکرده اید، اکنون این کار را انجام دهید.

      اگر قبلاً یک دامنه Dynamic Links ایجاد کرده‌اید، به آن توجه داشته باشید. یک دامنه Dynamic Links معمولاً مانند مثال زیر است:

      example.page.link

      هنگامی که برنامه Apple یا Android خود را برای رهگیری پیوند ورودی پیکربندی می کنید، به این مقدار نیاز خواهید داشت.

  2. پیکربندی برنامه های اندروید:

    1. برای مدیریت این پیوندها از برنامه Android خود، نام بسته Android باید در تنظیمات پروژه Firebase Console مشخص شود. علاوه بر این، SHA-1 و SHA-256 گواهی درخواست باید ارائه شود.
    2. اکنون که یک دامنه پیوند پویا اضافه کرده‌اید و مطمئن شده‌اید که برنامه اندروید شما به درستی پیکربندی شده است، پیوند پویا به برنامه شما هدایت می‌شود و از فعالیت راه‌انداز شروع می‌شود.
    3. اگر می‌خواهید پیوند پویا به یک فعالیت خاص هدایت شود، باید یک فیلتر هدف را در فایل AndroidManifest.xml خود پیکربندی کنید. این را می توان با مشخص کردن دامنه پیوند پویا یا کنترل کننده اقدام ایمیل در فیلتر قصد انجام داد. به طور پیش فرض، کنترل کننده اقدام ایمیل در دامنه ای مانند مثال زیر میزبانی می شود:
      PROJECT_ID.firebaseapp.com/
    4. هشدارها:
      1. آدرس اینترنتی را که در actionCodeSettings تنظیم کرده اید در فیلتر قصد خود مشخص نکنید.
      2. هنگام ایجاد دامنه پیوند پویا، ممکن است یک لینک URL کوتاه نیز ایجاد کرده باشید. این URL کوتاه ارسال نخواهد شد. فیلتر قصد خود را طوری پیکربندی نکنید که آن را با ویژگی android:pathPrefix پیدا کند. این بدان معنی است که شما نمی توانید لینک های پویا مختلف را در قسمت های مختلف برنامه خود دریافت کنید. با این حال، می‌توانید پارامتر پرس و جوی mode را در پیوند بررسی کنید تا ببینید چه عملیاتی در تلاش است انجام شود، یا از روش‌های SDK مانند isSignInWithEmailLink استفاده کنید تا ببینید آیا پیوندی که برنامه شما دریافت کرده است، آنچه را که می‌خواهید انجام می‌دهد یا خیر.
    5. برای اطلاعات بیشتر در مورد دریافت پیوندهای پویا، به دستورالعمل‌های دریافت پیوندهای پویا اندروید مراجعه کنید.

پس از دریافت پیوند همانطور که در بالا توضیح داده شد، بررسی کنید که برای احراز هویت پیوند ایمیل است و ورود به سیستم را کامل کنید.

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

برای کسب اطلاعات بیشتر در مورد نحوه مدیریت ورود به سیستم با پیوند ایمیل در برنامه اپل، به راهنمای پلتفرم‌های اپل مراجعه کنید.

برای آشنایی با نحوه مدیریت ورود به سیستم با پیوند ایمیل در یک برنامه وب، به راهنمای وب مراجعه کنید.

همچنین می توانید این روش احراز هویت را به یک کاربر موجود پیوند دهید. برای مثال، کاربری که قبلاً با ارائه‌دهنده دیگری مانند شماره تلفن احراز هویت شده است، می‌تواند این روش ورود به سیستم را به حساب موجود خود اضافه کند.

تفاوت در نیمه دوم عملیات خواهد بود:

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

با این حال، از آنجایی که جریان ممکن است به دستگاه دیگری ختم شود که کاربر اصلی در آن وارد نشده است، ممکن است این جریان تکمیل نشود. در این صورت می توان خطایی به کاربر نشان داد تا مجبور شود لینک را در همان دستگاه باز کند. برخی از حالت ها را می توان در پیوند ارسال کرد تا اطلاعاتی در مورد نوع عملیات و uid کاربر ارائه شود.

اگر پروژه خود را در تاریخ 15 سپتامبر 2023 یا پس از آن ایجاد کرده اید، حفاظت از شمارش ایمیل به طور پیش فرض فعال است. این ویژگی امنیت حساب‌های کاربری پروژه شما را بهبود می‌بخشد، اما متد fetchSignInMethodsForEmail() را غیرفعال می‌کند، که قبلاً برای پیاده‌سازی جریان‌های شناسه اول توصیه می‌کردیم.

اگرچه می توانید حفاظت از شمارش ایمیل را برای پروژه خود غیرفعال کنید، توصیه می کنیم این کار را نکنید.

برای جزئیات بیشتر به مستندات مربوط به حفاظت از شمارش ایمیل مراجعه کنید.

مراحل بعدی

پس از اینکه کاربر برای اولین بار وارد سیستم شد، یک حساب کاربری جدید ایجاد می‌شود و به اعتبارنامه‌ها (یعنی نام کاربری و رمز عبور، شماره تلفن یا اطلاعات ارائه‌دهنده تاییدیه) مرتبط می‌شود که کاربر با آن وارد شده است. این حساب جدید به‌عنوان بخشی از پروژه Firebase شما ذخیره می‌شود و می‌توان از آن برای شناسایی کاربر در همه برنامه‌های پروژه شما، صرف نظر از نحوه ورود کاربر به سیستم استفاده کرد.

  • در برنامه های خود، می توانید اطلاعات اولیه نمایه کاربر را از شی FirebaseUser دریافت کنید. به مدیریت کاربران مراجعه کنید.

  • در قوانین امنیتی Firebase Realtime Database و Cloud Storage خود، می‌توانید شناسه کاربری منحصر به فرد کاربر واردشده به سیستم را از متغیر auth دریافت کنید و از آن برای کنترل داده‌هایی که کاربر می‌تواند به آن دسترسی داشته باشد استفاده کنید.

می‌توانید به کاربران اجازه دهید با استفاده از چندین ارائه‌دهنده احراز هویت، با پیوند دادن اعتبار ارائه‌دهنده تأیید اعتبار به یک حساب کاربری موجود، به برنامه شما وارد شوند.

برای خروج از سیستم کاربر، signOut تماس بگیرید:

Kotlin+KTX

Firebase.auth.signOut()

Java

FirebaseAuth.getInstance().signOut();