مصادقة المستخدمين من خلال ميزة "تسجيل الدخول باستخدام حساب Google"

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

يرشدك هذا المستند إلى كيفية تنفيذ ميزة "تسجيل الدخول باستخدام حساب Google" في تطبيقات Android، وكيفية إعداد واجهة مستخدم زر "تسجيل الدخول باستخدام حساب Google"، وإعداد تجارب تسجيل الدخول بنقرة واحدة والمحسّنة للتطبيقات. لتسهيل عملية نقل البيانات من جهاز إلى آخر، تتيح ميزة "تسجيل الدخول باستخدام حساب Google" إمكانية تسجيل الدخول تلقائيًا، كما أنّ طبيعتها المتوافقة مع عدة منصات على Android وiOS والويب تساعدك في توفير إمكانية تسجيل الدخول إلى تطبيقك على أي جهاز. إذا كنت تستخدم خدمة Firebase Authentication لتطبيقك، يمكنك الاطّلاع على مزيد من المعلومات حول دمج ميزة "تسجيل الدخول باستخدام Google" وCredential Manager في دليل المصادقة باستخدام Google على Android.

لإعداد ميزة "تسجيل الدخول باستخدام حساب Google"، اتّبِع هاتين الخطوتَين الرئيسيتَين:

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

البطاقة السفلية في Credential Manager
الشكل 1. ورقة Credential Manager السفلية واجهة مستخدم اختيار بيانات الاعتماد

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

صورة متحرّكة تعرض عملية "تسجيل الدخول باستخدام حساب Google"
الشكل 2. واجهة مستخدم زر "تسجيل الدخول باستخدام حساب Google" في Credential Manager

يوضّح هذا المستند كيفية دمج زر "تسجيل الدخول باستخدام حساب Google" ومربّع الحوار في أسفل الشاشة مع Credential Manager API باستخدام مكتبة Google ID المساعدة.

إعداد مشروعك

  1. افتح مشروعك في ، أو أنشئ مشروعًا إذا لم يكن لديك مشروع.
  2. في ، تأكَّد من أنّ جميع المعلومات كاملة ودقيقة.
    1. تأكَّد من أنّ تطبيقك يتضمّن اسم تطبيق وشعار تطبيق وصفحة رئيسية صحيحة. سيتم عرض هذه القيم للمستخدمين على شاشة الموافقة الخاصة بميزة "تسجيل الدخول باستخدام حساب Google" عند الاشتراك وعلى شاشة التطبيقات والخدمات التابعة لجهات خارجية.
    2. تأكَّد من تحديد عناوين URL لسياسة الخصوصية وبنود الخدمة الخاصة بتطبيقك.
  3. في ، أنشئ معرّف عميل Android لتطبيقك إذا لم يكن لديك معرّف. عليك تحديد اسم حزمة تطبيقك وتوقيع SHA-1.
    1. انتقِل إلى .
    2. انقر على إنشاء عميل.
    3. اختَر نوع التطبيق Android.
  4. في ، أنشِئ معرّف عميل جديدًا من نوع "تطبيق ويب" إذا لم يسبق لك إجراء ذلك. يمكنك تجاهل الحقلَين "مصادر JavaScript المسموح بها" و "معرّفات الموارد المنتظمة (URI) المعتمَدة لإعادة التوجيه" في الوقت الحالي. سيتم استخدام معرّف العميل هذا لتحديد خادم الخلفية عندما يتواصل مع خدمات المصادقة من Google.
    1. انتقِل إلى .
    2. انقر على إنشاء عميل.
    3. اختَر نوع تطبيق الويب.

تعريف العناصر التابعة

في ملف build.gradle الخاص بالوحدة، حدِّد التبعيات باستخدام أحدث إصدار من Credential Manager:

dependencies {
  // ... other dependencies
  implementation "androidx.credentials:credentials:<latest version>"
  implementation "androidx.credentials:credentials-play-services-auth:<latest version>"
  implementation "com.google.android.libraries.identity.googleid:googleid:<latest version>"
}

إنشاء مثيل لطلب تسجيل الدخول باستخدام حساب Google

لبدء عملية التنفيذ، عليك إنشاء مثيل لطلب تسجيل الدخول باستخدام حساب Google. استخدِم GetGoogleIdOption لاسترداد رمز تعريف Google الخاص بالمستخدم.

val googleIdOption: GetGoogleIdOption = GetGoogleIdOption.Builder()
  .setFilterByAuthorizedAccounts(true)
  .setServerClientId(WEB_CLIENT_ID)
  .setAutoSelectEnabled(true)
  // nonce string to use when generating a Google ID token
  .setNonce(nonce)
.build()

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

إذا لم تتوفّر أي حسابات Google معتمَدة، يجب أن يُطلب من المستخدم الاشتراك باستخدام أي من حساباته المتاحة. لإجراء ذلك، اطلب من المستخدم إعادة الاتصال بواجهة برمجة التطبيقات وتعيين قيمة setFilterByAuthorizedAccounts إلى false. مزيد من المعلومات عن الاشتراك

تفعيل ميزة "تسجيل الدخول التلقائي" للمستخدمين المتكرّرين (يُنصح بذلك)

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

لتفعيل ميزة "تسجيل الدخول التلقائي"، استخدِم setAutoSelectEnabled(true). لا يمكن تسجيل الدخول تلقائيًا إلا عند استيفاء المعايير التالية:

  • هناك بيانات اعتماد واحدة تطابق الطلب، ويمكن أن تكون حساب Google أو كلمة مرور، وتتطابق بيانات الاعتماد هذه مع الحساب التلقائي على جهاز Android.
  • لم يسجّل المستخدم الخروج بشكل صريح.
  • لم يوقف المستخدم ميزة "تسجيل الدخول تلقائيًا" في إعدادات حساب Google.
val googleIdOption: GetGoogleIdOption = GetGoogleIdOption.Builder()
  .setFilterByAuthorizedAccounts(true)
  .setServerClientId(WEB_CLIENT_ID)
  .setAutoSelectEnabled(true)
  // nonce string to use when generating a Google ID token
  .setNonce(nonce)
.build()

تذكَّر التعامل مع تسجيل الخروج بشكل صحيح عند تنفيذ ميزة تسجيل الدخول التلقائي، حتى يتمكّن المستخدمون دائمًا من اختيار الحساب المناسب بعد تسجيل الخروج من تطبيقك بشكل صريح.

ضبط قيمة nonce لتحسين الأمان

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

val googleIdOption: GetGoogleIdOption = GetGoogleIdOption.Builder()
  .setFilterByAuthorizedAccounts(true)
  .setServerClientId(WEB_CLIENT_ID)
  .setAutoSelectEnabled(true)
  // nonce string to use when generating a Google ID token
  .setNonce(nonce)
.build()

إنشاء عملية "تسجيل الدخول باستخدام حساب Google"

في ما يلي خطوات إعداد عملية "تسجيل الدخول باستخدام Google":

  1. أنشئ مثيلاً من GetCredentialRequest، ثم أضِف googleIdOption الذي تم إنشاؤه سابقًا باستخدام addCredentialOption() لاسترداد بيانات الاعتماد.
  2. مرِّر هذا الطلب إلى استدعاء getCredential() (Kotlin) أو getCredentialAsync() (Java) لاسترداد بيانات الاعتماد المتاحة للمستخدم.
  3. بعد نجاح طلب البيانات من واجهة برمجة التطبيقات، استخرِج CustomCredential الذي يتضمّن نتيجة بيانات GoogleIdTokenCredential.
  4. يجب أن يكون نوع CustomCredential مساويًا لقيمة GoogleIdTokenCredential.TYPE_GOOGLE_ID_TOKEN_CREDENTIAL. حوِّل الكائن إلى GoogleIdTokenCredential باستخدام الطريقة GoogleIdTokenCredential.createFrom.
  5. في حال نجاح عملية التحويل، استخرِج معرّف GoogleIdTokenCredential، وتحقّق منه، وصادِق على بيانات الاعتماد على خادمك.

  6. إذا تعذّر التحويل وظهرت رسالة الخطأ GoogleIdTokenParsingException، قد تحتاج إلى تعديل إصدار مكتبة "تسجيل الدخول باستخدام حساب Google".

  7. التعرّف على أي أنواع بيانات اعتماد مخصّصة غير معروفة

val request: GetCredentialRequest = GetCredentialRequest.Builder()
  .addCredentialOption(googleIdOption)
  .build()

coroutineScope {
  try {
    val result = credentialManager.getCredential(
      request = request,
      context = activityContext,
    )
    handleSignIn(result)
  } catch (e: GetCredentialException) {
    // Handle failure
  }
}
fun handleSignIn(result: GetCredentialResponse) {
  // Handle the successfully returned credential.
  val credential = result.credential
  val responseJson: String

  when (credential) {

    // Passkey credential
    is PublicKeyCredential -> {
      // Share responseJson such as a GetCredentialResponse to your server to validate and
      // authenticate
      responseJson = credential.authenticationResponseJson
    }

    // Password credential
    is PasswordCredential -> {
      // Send ID and password to your server to validate and authenticate.
      val username = credential.id
      val password = credential.password
    }

    // GoogleIdToken credential
    is CustomCredential -> {
      if (credential.type == GoogleIdTokenCredential.TYPE_GOOGLE_ID_TOKEN_CREDENTIAL) {
        try {
          // Use googleIdTokenCredential and extract the ID to validate and
          // authenticate on your server.
          val googleIdTokenCredential = GoogleIdTokenCredential
            .createFrom(credential.data)
          // You can use the members of googleIdTokenCredential directly for UX
          // purposes, but don't use them to store or control access to user
          // data. For that you first need to validate the token:
          // pass googleIdTokenCredential.getIdToken() to the backend server.
          // see [validation instructions](https://developers.google.com/identity/gsi/web/guides/verify-google-id-token)
        } catch (e: GoogleIdTokenParsingException) {
          Log.e(TAG, "Received an invalid google id token response", e)
        }
      } else {
        // Catch any unrecognized custom credential type here.
        Log.e(TAG, "Unexpected type of credential")
      }
    }

    else -> {
      // Catch any unrecognized credential type here.
      Log.e(TAG, "Unexpected type of credential")
    }
  }
}

بدء عملية زر "تسجيل الدخول باستخدام حساب Google"

لتفعيل مسار زر "تسجيل الدخول باستخدام حساب Google"، استخدِم GetSignInWithGoogleOption بدلاً من GetGoogleIdOption:

val signInWithGoogleOption: GetSignInWithGoogleOption = GetSignInWithGoogleOption.Builder(
  serverClientId = WEB_CLIENT_ID
).setNonce(nonce)
  .build()

تعامَل مع GoogleIdTokenCredential الذي تم عرضه على النحو الموضّح في مثال الرمز البرمجي التالي.

fun handleSignInWithGoogleOption(result: GetCredentialResponse) {
  // Handle the successfully returned credential.
  val credential = result.credential

  when (credential) {
    is CustomCredential -> {
      if (credential.type == GoogleIdTokenCredential.TYPE_GOOGLE_ID_TOKEN_CREDENTIAL) {
        try {
          // Use googleIdTokenCredential and extract id to validate and
          // authenticate on your server.
          val googleIdTokenCredential = GoogleIdTokenCredential
            .createFrom(credential.data)
        } catch (e: GoogleIdTokenParsingException) {
          Log.e(TAG, "Received an invalid google id token response", e)
        }
      }
      else {
        // Catch any unrecognized credential type here.
        Log.e(TAG, "Unexpected type of credential")
      }
    }

    else -> {
      // Catch any unrecognized credential type here.
      Log.e(TAG, "Unexpected type of credential")
    }
  }
}

بعد إنشاء مثيل لطلب تسجيل الدخول باستخدام حساب Google، ابدأ عملية المصادقة بالطريقة نفسها الموضّحة في قسم تسجيل الدخول باستخدام حساب Google.

تفعيل خيار الاشتراك للمستخدمين الجدد (إجراء يُنصح به)

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

إذا لم يتم العثور على أي بيانات اعتماد محفوظة (لم يتم عرض أي حسابات Google من خلال getGoogleIdOption)، اطلب من المستخدم الاشتراك. تحقَّق أولاً من setFilterByAuthorizedAccounts(true) لمعرفة ما إذا كانت هناك أي حسابات مستخدَمة سابقًا. إذا لم يتم العثور على أي منها، اطلب من المستخدم الاشتراك باستخدام حسابه على Google باستخدام setFilterByAuthorizedAccounts(false)

مثال:

val googleIdOption: GetGoogleIdOption = GetGoogleIdOption.Builder()
  .setFilterByAuthorizedAccounts(false)
  .setServerClientId(WEB_CLIENT_ID)
  .build()

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

تسجيل الخروج من الاسم المعرِّف

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

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