افزودن اصالت‌سنجی چندعاملی TOTP به برنامه Android

اگر به Firebase Authentication with Identity Platform ارتقا داده‌اید، می‌توانید اصالت‌سنجی چندعاملی (MFA) گذرواژه یکباره زمان‌مبنا (TOTP) را به برنامه‌تان اضافه کنید.

Firebase Authentication with Identity Platform به شما امکان می‌دهد از گذرواژه یک‌بارمصرف زمان‌مبنا به‌عنوان عامل اضافی برای اصالت‌سنجی چندعاملی استفاده کنید. وقتی این ویژگی را فعال می‌کنید، کاربرانی که می‌خواهند به سیستم برنامه‌تان وارد شوند، درخواستی برای TOTP می‌بینند. برای تولید آن، باید از برنامه اصالت‌سنجی‌ای استفاده کنند که بتواند کدهای TOTP معتبر تولید کند، مثل Google Authenticator.

قبل از شروع

  1. حداقل یک ارائه‌دهنده را که از MFA پشتیبانی می‌کند فعال کنید. توجه داشته باشید که همه ارائه‌دهندگان به‌جز موارد زیر از «احراز هویت چندعاملی» پشتیبانی می‌کنند:

    • احراز هویت تلفن
    • احراز هویت ناشناس
    • کدهای اصالت‌سنجی سفارشی
    • Apple Game Center
  2. مطمئن شوید برنامه‌تان نشانی ایمیل کاربران را درستی‌سنجی می‌کند. احراز هویت چندعاملی به درستی‌سنجی ایمیل نیاز دارد. این کار از ثبت‌نام عاملان بدخواه در سرویس با نشانی ایمیلی که متعلق به آن‌ها نیست و سپس قفل کردن دسترسی مالک واقعی نشانی ایمیل با افزودن عامل دوم جلوگیری می‌کند.

  3. اگر قبلاً این کار را نکرده‌اید، کیت توسعه نرم‌افزار Firebase ویژه Android را نصب کنید.

    احراز هویت چندعاملی با گذرواژه یک‌بارمصرف زمان‌مبنا فقط در کیت توسعه نرم‌افزار Android نسخه v22.1.0 و بالاتر پشتیبانی می‌شود.

فعال کردن «احراز هویت چندعاملی گذرواژه یک‌بارمصرف زمان‌مبنا»

برای فعال کردن TOTP به‌عنوان عامل دوم، از Admin SDK استفاده کنید یا با نقطه پایانی REST پیکربندی پروژه تماس بگیرید.

برای استفاده از Admin SDK، کارهای زیر را انجام دهید:

  1. اگر قبلاً این کار را نکرده‌اید، کیت توسعه نرم‌افزار Firebase Admin Node.js را نصب کنید.

    TOTP MFA فقط در «کیت توسعه نرم‌افزار Firebase Admin Node.js» نسخه ۱۱.۶.۰ و بالاتر پشتیبانی می‌شود.

  2. موارد زیر را اجرا کنید:

    import { getAuth } from 'firebase-admin/auth';
    
    getAuth().projectConfigManager().updateProjectConfig(
    {
          multiFactorConfig: {
              providerConfigs: [{
                  state: "ENABLED",
                  totpProviderConfig: {
                      adjacentIntervals: NUM_ADJ_INTERVALS
                  }
              }]
          }
    })
    

    موارد زیر را جایگزین کنید:

    • ‫NUM_ADJ_INTERVALS: تعداد بازه‌های زمانی مجاور که «گذرواژه‌های یک‌باره زمان‌مبنا» از آن‌ها پذیرفته می‌شود، از صفر تا ده. پیش‌فرض پنج است.

      نحوه عملکرد گذرواژه یک‌بارمصرف زمان‌مبنا به این صورت است که وقتی دو طرف (اثبات‌کننده و اعتبارسنج) گذرواژه یک‌بارمصرف را در یک پنجره زمانی یکسان (معمولاً ۳۰ ثانیه) تولید می‌کنند، گذرواژه یکسانی تولید می‌شود. بااین‌حال، برای تطبیق دادن انحراف ساعت بین طرفین و زمان پاسخ انسان، می‌توانید سرویس TOTP را پیکربندی کنید تا TOTP را از پنجره‌های مجاور نیز بپذیرد.

برای فعال کردن «احراز هویت چندعاملی گذرواژه یک‌بارمصرف زمان‌مبنا» بااستفاده از REST API، دستور زیر را اجرا کنید:

curl -X PATCH "https://identitytoolkit.googleapis.com/admin/v2/projects/PROJECT_ID/config?updateMask=mfa" \
    -H "Authorization: Bearer $(gcloud auth print-access-token)" \
    -H "Content-Type: application/json" \
    -H "X-Goog-User-Project: PROJECT_ID" \
    -d \
    '{
        "mfa": {
          "providerConfigs": [{
            "state": "ENABLED",
            "totpProviderConfig": {
              "adjacentIntervals": NUM_ADJ_INTERVALS
            }
          }]
       }
    }'

موارد زیر را جایگزین کنید:

  • ‫PROJECT_ID: شناسه پروژه.
  • NUM_ADJ_INTERVALS: تعداد بازه‌های زمانی، از صفر تا ده. پیش‌فرض پنج است.

    نحوه عملکرد گذرواژه یک‌بارمصرف زمان‌مبنا به این صورت است که وقتی دو طرف (اثبات‌کننده و اعتبارسنج) گذرواژه یک‌بارمصرف را در یک پنجره زمانی یکسان (معمولاً ۳۰ ثانیه) تولید می‌کنند، گذرواژه یکسانی تولید می‌شود. بااین‌حال، برای تطبیق دادن انحراف ساعت بین طرفین و زمان پاسخ انسان، می‌توانید سرویس TOTP را پیکربندی کنید تا TOTP را از پنجره‌های مجاور نیز بپذیرد.

انتخاب الگوی ثبت‌نام

می‌توانید انتخاب کنید که آیا برنامه‌تان به اصالت‌سنجی چندعاملی نیاز دارد یا نه، و چگونه و چه زمانی کاربران را ثبت‌نام کنید. برخی‌از الگوهای رایج عبارت‌اند از:

  • عامل دوم کاربر را به‌عنوان بخشی از ثبت‌نام ثبت کنید. اگر برنامه‌تان برای همه کاربران به اصالت‌سنجی چندعاملی نیاز دارد، از این روش استفاده کنید.

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

  • امکان افزودن عامل دوم از صفحه مدیریت حساب یا نمایه کاربر، به‌جای صفحه ثبت‌نام، فراهم شود. این کار اصطکاک را درطول فرایند ثبت‌نام به‌حداقل می‌رساند و درعین‌حال اصالت‌سنجی چندعاملی را برای کاربران حساس به امنیت دردسترس قرار می‌دهد.

  • وقتی کاربر می‌خواهد به ویژگی‌هایی با الزامات امنیتی بیشتر دسترسی پیدا کند، افزودن عامل دوم به‌صورت افزایشی الزامی است.

ثبت‌نام کاربران در «احراز هویت چندعاملی گذرواژه یک‌باره زمان‌مبنا»

پس‌از فعال کردن «احراز هویت چندعاملی گذرواژه یک‌باره زمان‌مبنا» به‌عنوان عامل دوم برای برنامه‌تان، منطق سمت کارخواه را برای ثبت‌نام کاربران در «احراز هویت چندعاملی گذرواژه یک‌باره زمان‌مبنا» پیاده‌سازی کنید:

  1. اصالت‌سنجی مجدد کاربر.

  2. تولید کردن کلید TOTP برای کاربر اصالت‌سنجی‌شده:

    // Generate a TOTP secret.
    Firebase.auth.currentUser.multiFactor.session
        .addOnSuccessListener { multiFactorSession ->
            TotpMultiFactorGenerator.generateSecret(multiFactorSession)
                .addOnSuccessListener { totpSecret ->
                    // Display the secret to the user and prompt them to
                    // enter it into their authenticator app. (See the next
                    // step.)
                }
        }
    
  3. رمز را به کاربر نشان دهید و از او بخواهید آن را در برنامه اصالت‌سنجی خود وارد کند:

    // Display this key:
    val secret = totpSecret.sharedSecretKey
    

    علاوه‌بر نمایش کلید امن، می‌توانید آن را به‌طور خودکار به برنامه اصالت‌سنجی پیش‌فرض دستگاه اضافه کنید. برای انجام این کار، یک شناسه منبع یکسان سازگار با Google Authenticator تولید کنید و آن را به openInOtpApp() ارسال کنید:

    val qrCodeUri = totpSecret.generateQrCodeUrl(
        currentUser.email ?: "default account",
        "Your App Name")
    totpSecret.openInOtpApp(qrCodeUri)
    

    پس‌از اینکه کاربر کلید خصوصی خود را به برنامه اصالت‌سنجی اضافه کرد، برنامه شروع به تولید گذرواژه‌های یک‌باره زمان‌مبنا می‌کند.

  4. از کاربر بخواهید «گذرواژه یک‌باره زمان‌مبنا» (TOTP) نمایش‌داده‌شده در برنامه اصالت‌سنجی را تایپ کند و از آن برای نهایی کردن ثبت‌نام در «احراز هویت چندعاملی» استفاده کند:

    // Ask the user for a verification code from the authenticator app.
    val verificationCode = // Code from user input.
    
    // Finalize the enrollment.
    val multiFactorAssertion = TotpMultiFactorGenerator
        .getAssertionForEnrollment(totpSecret, verificationCode)
    Firebase.auth.currentUser.multiFactor.enroll(multiFactorAssertion, "TOTP")
        .addOnSuccessListener {
            // Enrollment complete.
        }
    

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

برای وارد کردن کاربران به سیستم بااستفاده از «احراز هویت چندعاملی گذرواژه یک‌بارمصرف زمان‌مبنا»، از کد زیر استفاده کنید:

  1. یکی از روش‌های signInWith- را فراخوانی کنید، همان‌طور که اگر از MFA استفاده نمی‌کردید انجام می‌دادید. (برای مثال، signInWithEmailAndPassword().) اگر روش FirebaseAuthMultiFactorException را برمی‌گرداند، جریان MFA برنامه‌تان را شروع کنید.

    Firebase.auth.signInWithEmailAndPassword(email, password)
        .addOnSuccessListener { result ->
            // If the user is not enrolled with a second factor and provided valid
            // credentials, sign-in succeeds.
    
            // (If your app requires MFA, this could be considered an error
            // condition, which you would resolve by forcing the user to enroll a
            // second factor.)
    
            // ...
        }
        .addOnFailureListener { exception ->
            when (exception) {
                is FirebaseAuthMultiFactorException -> {
                    // Initiate your second factor sign-in flow. (See next step.)
                    // ...
                }
            }
        }
    
  2. جریان MFA برنامه شما باید ابتدا از کاربر بخواهد عامل دوم موردنظرش را برای استفاده انتخاب کند. می‌توانید با بررسی ویژگی hints از نمونه MultiFactorResolver، فهرستی از عوامل دوم پشتیبانی‌شده را دریافت کنید:

    val enrolledFactors = exception.resolver.hints.map { it.displayName }
    
  3. اگر کاربر انتخاب کند که از TOTP استفاده کند، از او بخواهید TOTP نمایش‌داده‌شده در برنامه اصالت‌سنجی خود را تایپ کند و از آن برای ورود به سیستم استفاده کند:

    when (exception.resolver.hints[selectedIndex].factorId) {
        TotpMultiFactorGenerator.FACTOR_ID -> {
            val otpFromAuthenticator = // OTP typed by the user.
            val assertion = TotpMultiFactorGenerator.getAssertionForSignIn(
                exception.resolver.hints[selectedIndex].uid,
                otpFromAuthenticator
            )
            exception.resolver.resolveSignIn(assertion)
                .addOnSuccessListener { result ->
                    // Successfully signed in!
                }
                .addOnFailureListener { resolveError ->
                    // Invalid or expired OTP.
                }
        }
        PhoneMultiFactorGenerator.FACTOR_ID -> {
            // Handle SMS second factor.
        }
    }
    

لغو ثبت‌نام از «احراز هویت چندعاملی گذرواژه یک‌بارمصرف زمان‌مبنا»

این بخش نحوه رسیدگی به لغو ثبت‌نام کاربر از «احراز هویت چندعاملی گذرواژه یک‌بارمصرف زمان‌مبنا» را شرح می‌دهد.

اگر کاربری برای چند گزینه «احراز هویت چندعاملی» ثبت‌نام کرده باشد و از جدیدترین گزینه فعال‌شده لغو ثبت‌نام کند، auth/user-token-expired دریافت می‌کند و از سیستم خارج می‌شود. کاربر باید دوباره به سیستم وارد شود و اعتبارنامه‌های موجود خود را (برای مثال، نشانی ایمیل و گذرواژه) به‌تأیید برساند.

برای لغو ثبت‌نام کاربر، رسیدگی به خطا، و راه‌اندازی اصالت‌سنجی مجدد، از کد زیر استفاده کنید:

Firebase.auth.currentUser.multiFactor.unenroll(mfaEnrollmentId)
    .addOnSuccessListener {
        // Second factor unenrolled.
    }
    .addOnFailureListener { exception ->
        when (exception) {
            is FirebaseAuthInvalidUserException -> {
                // Second factor unenrolled. If the user was signed out, re-authenticate
                // them.

                // For example, if they signed in with a password, prompt them to
                // provide it again, then call `reauthenticateWithCredential()` as shown
                // below.
                val credential = EmailAuthProvider.getCredential(email, password)
                currentUser.reauthenticate(credential)
                    .addOnSuccessListener { 
                        // Success!
                    }
                    .addOnFailureListener { 
                        // Bad email address and password combination.
                    }
            }
        }
    }

حالا چه می‌شود