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

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

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

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

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

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

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

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

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

إعداد مشروعك على Google APIs Console

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

الإفصاح عن التبعيات

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

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)
  .setNonce(<nonce string to use when generating a Google ID token>)
  .build()

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

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

تفعيل ميزة "تسجيل الدخول التلقائي" للمستخدمين المتكررين (إجراء مقترَح)

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

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

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

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

ضبط قيمة عشوائية لتحسين الأمان

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

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

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

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

  1. أنشئ مثيلًا لـ GetCredentialRequest، ثم أضِف googleIdOption الذي تم إنشاؤه سابقًا باستخدام addCredentialOption() لاسترداد بيانات اعتماد GetCredentialRequest.
  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 = Builder()
  .addCredentialOption(googleIdOption)
  .build()

coroutineScope.launch {
  try {
    val result = credentialManager.getCredential(
      request = request,
      context = activityContext,
    )
    handleSignIn(result)
  } catch (e: GetCredentialException) {
    handleFailure(e)
  }
}

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

  when (credential) {

    // Passkey credential
    is PublicKeyCredential -> {
      // Share responseJson such as a GetCredentialResponse on 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.
          GoogleIdTokenVerifier verifier = ... // see validation instructions
          GoogleIdToken idToken = verifier.verify(idTokenString);
          // To get a stable account identifier (e.g. for storing user data),
          // use the subject ID:
          idToken.getPayload().getSubject()
        } 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()
  .setServerClientId(WEB_CLIENT_ID)
  .setNonce(<nonce string to use when generating a Google ID token>)
  .build()

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

fun handleSignIn(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() لمحو حالة بيانات اعتماد المستخدم الحالية من جميع مزوّدي بيانات الاعتماد. سيؤدي ذلك إلى إعلام جميع مقدّمي بيانات الاعتماد بأنّه يجب محو أي جلسة بيانات اعتماد مخزّنة ل التطبيق المحدّد.

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