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

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

مزایای بی‌شماری برای ورود از طریق ایمیل وجود دارد:

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

قبل از اینکه شروع کنی

پروژه اندروید خود را تنظیم کنید

  1. اگر هنوز Firebase را به پروژه اندروید خود اضافه نکرده‌اید، آن را اضافه کنید.

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

    همچنین، به عنوان بخشی از راه‌اندازی Firebase Authentication ، باید SDK سرویس‌های گوگل پلی را به برنامه خود اضافه کنید.

    dependencies {
        // Import the BoM for the Firebase platform
        implementation(platform("com.google.firebase:firebase-bom:34.9.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.5.0")
    }

    با استفاده از Firebase Android BoM ، برنامه شما همیشه از نسخه‌های سازگار کتابخانه‌های اندروید Firebase استفاده خواهد کرد.

    (جایگزین) اضافه کردن وابستگی‌های کتابخانه 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:24.0.1")
    // Also add the dependency for the Google Play services library and specify its version implementation("com.google.android.gms:play-services-auth:21.5.0")
    }

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

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

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

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

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

    • url : لینک عمیق برای جاسازی و هر وضعیت اضافی که باید منتقل شود. دامنه‌ی لینک باید در فهرست دامنه‌های مجاز کنسول Firebase در لیست سفید قرار داشته باشد که می‌توانید با رفتن به تب روش ورود (Authentication -> Sign-in method) آن را پیدا کنید. اگر برنامه روی دستگاه کاربر نصب نشده باشد و برنامه قابل نصب نباشد، این لینک کاربر را به این URL هدایت می‌کند.
    • androidPackageName و iOSBundleId : به Firebase Authentication کمک می‌کند تا تعیین کند که آیا باید یک لینک فقط وب یا موبایل ایجاد کند که روی دستگاه اندروید یا اپل باز شود.
    • 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، به بخش Passing State در Email Actions مراجعه کنید.

  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 استفاده می‌کنید تا از رهگیری احتمالی لینک شما توسط سرورهای واسطه جلوگیری شود.

تکمیل ورود به سیستم در یک برنامه اندروید

Firebase Authentication از Firebase Hosting برای ارسال لینک ایمیل به دستگاه تلفن همراه استفاده می‌کند. برای تکمیل ورود به سیستم از طریق برنامه تلفن همراه، برنامه باید طوری پیکربندی شود که لینک برنامه ورودی را تشخیص دهد، لینک عمیق زیرین را تجزیه کند و سپس ورود به سیستم را تکمیل کند. برای کسب اطلاعات بیشتر، به مستندات لینک‌های برنامه اندروید مراجعه کنید.

پیکربندی Firebase Hosting

Firebase Authentication هنگام ایجاد و ارسال لینکی که قرار است در یک برنامه تلفن همراه باز شود، از دامنه‌های Firebase Hosting استفاده می‌کند. یک دامنه Firebase Hosting پیش‌فرض از قبل برای شما پیکربندی شده است.

  1. پیکربندی دامنه‌های Firebase Hosting :

    در کنسول Firebase ، بخش هاستینگ (Hosting) را باز کنید.

    • اگر می‌خواهید از دامنه پیش‌فرض برای لینک ایمیلی که در برنامه‌های تلفن همراه باز می‌شود استفاده کنید، به سایت پیش‌فرض خود بروید و دامنه Hosting پیش‌فرض خود را یادداشت کنید. یک دامنه Hosting پیش‌فرض معمولاً به این شکل است: PROJECT_ID .firebaseapp.com .

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

    • اگر می‌خواهید از یک دامنه سفارشی برای لینک ایمیل استفاده کنید، می‌توانید یکی را در Firebase Hosting ثبت کنید و از آن برای دامنه لینک استفاده کنید.

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

    برای مدیریت این لینک‌ها از برنامه اندروید خود، نام بسته برنامه شما باید در تنظیمات پروژه کنسول Firebase مشخص شود. علاوه بر این، SHA-1 و SHA-256 گواهی برنامه باید ارائه شود.

    اگر می‌خواهید این لینک‌ها به یک اکتیویتی خاص هدایت شوند، باید یک فیلتر intent در فایل AndroidManifest.xml خود پیکربندی کنید. فیلتر intent باید لینک‌های ایمیل دامنه شما را دریافت کند. در 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 و طرح و میزبان مشخص شده توسط شما را باز می‌کنند، برنامه شما اکتیویتی را با این فیلتر intent برای مدیریت لینک آغاز می‌کند.

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

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

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

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

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

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

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 متکی بود که در ۲۵ آگوست ۲۰۲۵ غیرفعال خواهد شد.

ما یک راهکار جایگزین در Firebase Authentication Android SDK نسخه ۲۳.۲.۰+ و Firebase BoM نسخه ۳۳.۹.۰+ منتشر کرده‌ایم.

اگر برنامه شما از لینک‌های سبک قدیمی استفاده می‌کند، باید برنامه خود را به سیستم جدید مبتنی بر Firebase Hosting منتقل کنید.

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

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

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

مراحل بعدی

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

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

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

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

برای خروج کاربر، signOut را فراخوانی کنید:

Kotlin

Firebase.auth.signOut()

Java

FirebaseAuth.getInstance().signOut();