تسجيل الدخول إلى الحساب المرتبط على أجهزة Android

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

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

يوضّح هذا المستند كيفية تعديل تطبيق Android ليتوافق مع ميزة "تسجيل الدخول باستخدام حساب مرتبط".

آلية العمل

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

الإعداد

إعداد بيئة التطوير

احصل على أحدث إصدار من "خدمات Google Play" على جهاز التطوير المضيف باتّباع الخطوات التالية:

  1. افتح Android SDK Manager.
  1. ضِمن أدوات حزمة تطوير البرامج (SDK)، ابحث عن خدمات Google Play.

  2. إذا لم تكن حالة هذه الحِزم "مثبّتة"، حدِّدها كلّها وانقر على تثبيت الحِزم.

إعداد تطبيقك

  1. في ملف build.gradle على مستوى المشروع، أدرِج مستودع Maven الخاص بـ Google في كل من القسمَين buildscript وallprojects.

    buildscript {
        repositories {
            google()
        }
    }
    
    allprojects {
        repositories {
            google()
        }
    }
    
  2. أضِف الاعتماديات الخاصة بواجهة برمجة التطبيقات "الربط بحساب Google" إلى ملف Gradle على مستوى التطبيق الخاص بالوحدة، والذي يكون عادةً app/build.gradle:

    dependencies {
      implementation 'com.google.android.gms:play-services-auth:21.3.0'
    }
    

تعديل تطبيق Android ليتوافق مع ميزة "تسجيل الدخول باستخدام حساب مرتبط"

في نهاية عملية تسجيل الدخول باستخدام حساب مرتبط، يتم عرض رمز مميّز للمعرّف في تطبيقك. ويجب التأكّد من سلامة الرمز المميّز للمعرّف قبل تسجيل دخول المستخدم.

يوضّح نموذج الرمز البرمجي التالي خطوات استرداد الرمز المميّز لتعريف الهوية والتحقّق منه، ثم تسجيل دخول المستخدم.

  1. إنشاء نشاط لتلقّي نتيجة عنصر intent الخاص بتسجيل الدخول

    Kotlin

      private val activityResultLauncher = registerForActivityResult(
        ActivityResultContracts.StartIntentSenderForResult()) { result ->
        if (result.resultCode == RESULT_OK) {
          try {
            val signInCredentials = Identity.signInClient(this)
                                    .signInCredentialFromIntent(result.data)
            // Review the Verify the integrity of the ID token section for
            // details on how to verify the ID token
            verifyIdToken(signInCredential.googleIdToken)
          } catch (e: ApiException) {
            Log.e(TAG, "Sign-in failed with error code:", e)
          }
        } else {
          Log.e(TAG, "Sign-in failed")
        }
      }
    

    Java

      private final ActivityResultLauncher<IntentSenderResult>
        activityResultLauncher = registerForActivityResult(
        new ActivityResultContracts.StartIntentSenderForResult(),
        result -> {
        If (result.getResultCode() == RESULT_OK) {
            try {
              SignInCredential signInCredential = Identity.getSignInClient(this)
                             .getSignInCredentialFromIntent(result.getData());
              verifyIdToken(signInCredential.getGoogleIdToken());
            } catch (e: ApiException ) {
              Log.e(TAG, "Sign-in failed with error:", e)
            }
        } else {
            Log.e(TAG, "Sign-in failed")
        }
    });
    
  2. إنشاء طلب تسجيل الدخول

    Kotlin

    private val tokenRequestOptions =
    GoogleIdTokenRequestOptions.Builder()
      .supported(true)
      // Your server's client ID, not your Android client ID.
      .serverClientId(getString("your-server-client-id")
      .filterByAuthorizedAccounts(true)
      .associateLinkedAccounts("service-id-of-and-defined-by-developer",
                               scopes)
      .build()
    

    Java

     private final GoogleIdTokenRequestOptions tokenRequestOptions =
         GoogleIdTokenRequestOptions.Builder()
      .setSupported(true)
      .setServerClientId("your-service-client-id")
      .setFilterByAuthorizedAccounts(true)
      .associateLinkedAccounts("service-id-of-and-defined-by-developer",
                                scopes)
      .build()
    
  3. إطلاق Sign-In Pending intent

    Kotlin

     Identity.signInClient(this)
        .beginSignIn(
      BeginSignInRequest.Builder()
        .googleIdTokenRequestOptions(tokenRequestOptions)
      .build())
        .addOnSuccessListener{result ->
          activityResultLauncher.launch(result.pendingIntent.intentSender)
      }
      .addOnFailureListener {e ->
        Log.e(TAG, "Sign-in failed because:", e)
      }
    

    Java

     Identity.getSignInClient(this)
      .beginSignIn(
        BeginSignInRequest.Builder()
          .setGoogleIdTokenRequestOptions(tokenRequestOptions)
          .build())
      .addOnSuccessListener(result -> {
        activityResultLauncher.launch(
            result.getPendingIntent().getIntentSender());
    })
    .addOnFailureListener(e -> {
      Log.e(TAG, "Sign-in failed because:", e);
    });
    

التحقّق من سلامة رمز التعريف

استخدام إحدى مكتبات عملاء Google API

يُنصح باستخدام مكتبة عميل واجهة Google API للغة Java للتحقّق من صحة رموز التعريف المميزة من Google في بيئة التشغيل الفعلي.

Java

  import com.google.api.client.googleapis.auth.oauth2.GoogleIdToken;
  import com.google.api.client.googleapis.auth.oauth2.GoogleIdToken.Payload;
  import com.google.api.client.googleapis.auth.oauth2.GoogleIdTokenVerifier;

  ...

  GoogleIdTokenVerifier verifier = new GoogleIdTokenVerifier.Builder(transport, jsonFactory)
      // Specify the CLIENT_ID of the app that accesses the backend:
      .setAudience(Collections.singletonList(CLIENT_ID))
      // Or, if multiple clients access the backend:
      //.setAudience(Arrays.asList(CLIENT_ID_1, CLIENT_ID_2, CLIENT_ID_3))
      .build();

  // (Receive idTokenString by HTTPS POST)

  GoogleIdToken idToken = verifier.verify(idTokenString);
  if (idToken != null) {
    Payload payload = idToken.getPayload();

    // Print user identifier
    String userId = payload.getSubject();
    System.out.println("User ID: " + userId);

    // Get profile information from payload
    String email = payload.getEmail();
    boolean emailVerified = Boolean.valueOf(payload.getEmailVerified());
    String name = (String) payload.get("name");
    String pictureUrl = (String) payload.get("picture");
    String locale = (String) payload.get("locale");
    String familyName = (String) payload.get("family_name");
    String givenName = (String) payload.get("given_name");

    // Use or store profile information
    // ...

  } else {
    System.out.println("Invalid ID token.");
  }

تتحقّق طريقة GoogleIdTokenVerifier.verify() من توقيع JWT، ومن المطالبة aud، والمطالبة iss، والمطالبة exp.

إذا كنت بحاجة إلى التأكّد من أنّ رمز التعريف المميّز يمثّل حساب مؤسسة على Google Workspace أو Cloud، يمكنك التحقّق من صحة مطالبة hd من خلال التحقّق من اسم النطاق الذي تعرضه الطريقة Payload.getHostedDomain().