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

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

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

وستتعرف في هذا المستند على كيفية تعديل تطبيق Android تسجيل الدخول إلى حساب مرتبط

آلية العمل

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

ضبط إعدادات الجهاز

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

احصل على أحدث "خدمات Google Play" من خلال مضيف التطوير:

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

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

إعداد تطبيقك

  1. في ملف build.gradle على مستوى مشروعك، أضِف مستودع Maven من Google. في كل من القسمين buildscript وallprojects.

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

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

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

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

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

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

    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. فتح رسالة الغرض من تسجيل الدخول في انتظار المراجعة

    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 الرمز المميّز لرقم التعريف بشكل صحيح. استخدِم مفاتيح Google العامة (المتوفّرة بتنسيق JWK أو PEM) للتحقّق من توقيع الرمز المميّز. يتم تدوير هذه المفاتيح بانتظام، لذا يمكنك فحص عنوان Cache-Control في الاستجابة لتحديد الوقت المناسب لاستردادها مرة أخرى.
  • قيمة aud في الرمز المميّز للرقم التعريفي تساوي أحد معرِّفات عملاء تطبيقك. وتُعدّ عملية التحقّق هذه ضرورية لمنع الرموز المميّزة لرقم التعريف التي يتم إصدارها لتطبيق ضار عند استخدامها للوصول إلى بيانات المستخدم نفسه على خادم الخلفية في تطبيقك.
  • قيمة iss في الرمز المميّز للمعرّف تساوي accounts.google.com أو https://accounts.google.com.
  • لم يمر وقت انتهاء صلاحية (exp) الرمز المميّز للمعرّف.
  • إذا كنت بحاجة إلى التحقق من أنّ الرمز المميّز لرقم التعريف يمثّل حساب مؤسسة على Google Workspace أو Cloud، يمكنك مراجعة مطالبة hd التي تشير إلى النطاق المستضاف للمستخدم. ويجب استخدام هذه الطريقة عند تقييد الوصول إلى مورد معيّن على أعضاء نطاقات معيّنة فقط. في حال عدم تقديم هذا الادّعاء، يشير إلى أنّ الحساب لا ينتمي إلى نطاق تستضيفه Google.

بدلاً من كتابة الرمز الخاص بك لتنفيذ خطوات إثبات الملكية هذه، ننصحك بشدة باستخدام مكتبة عميل Google API للنظام الأساسي الذي تستخدمه أو مكتبة JWT للأغراض العامة. لأغراض التطوير وتصحيح الأخطاء، يمكنك استدعاء نقطة نهاية التحقّق من صحة tokeninfo.

استخدام مكتبة برامج Google API

باستخدام مكتبة برامج Java في Google API هي الطريقة الموصى بها لإثبات صحة الرموز المميّزة لمعرّف 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().

جارٍ استدعاء نقطة نهاية iconinfo

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

للتحقّق من صحة رمز مميّز للمعرّف باستخدام نقطة النهاية tokeninfo، يمكنك تقديم طلب HTTPS POST أو GET إلى نقطة النهاية، وإدخال الرمز المميّز للمعرّف في معلَمة id_token. على سبيل المثال، للتحقق من الرمز المميز "XYZ123"، قم بإجراء طلب GET التالي:

https://oauth2.googleapis.com/tokeninfo?id_token=XYZ123

إذا تم توقيع الرمز المميّز بشكل صحيح وكانت مطالبتا iss وexp تتضمّنان القيم المتوقّعة، ستتلقّى استجابة HTTP 200، حيث يحتوي النص على مطالبات الرمز المميّز للمعرّف بتنسيق JSON. إليك مثال على الرد:

{
 // These six fields are included in all Google ID Tokens.
 "iss": "https://accounts.google.com",
 "sub": "110169484474386276334",
 "azp": "1008719970978-hb24n2dstb40o45d4feuo2ukqmcc6381.apps.googleusercontent.com",
 "aud": "1008719970978-hb24n2dstb40o45d4feuo2ukqmcc6381.apps.googleusercontent.com",
 "iat": "1433978353",
 "exp": "1433981953",

 // These seven fields are only included when the user has granted the "profile" and
 // "email" OAuth scopes to the application.
 "email": "testuser@gmail.com",
 "email_verified": "true",
 "name" : "Test User",
 "picture": "https://lh4.googleusercontent.com/-kYgzyAWpZzJ/ABCDEFGHI/AAAJKLMNOP/tIXL9Ir44LE/s99-c/photo.jpg",
 "given_name": "Test",
 "family_name": "User",
 "locale": "en"
}

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