ورود به سیستم حساب پیوندی برای Android

ورود به سیستم حساب پیوندی، ورود با یک ضربه با Google را برای کاربرانی که از قبل حساب Google خود را به سرویس شما مرتبط کرده‌اند، فعال می‌کند. این تجربه را برای کاربران بهبود می بخشد زیرا آنها می توانند با یک کلیک بدون وارد کردن نام کاربری و رمز عبور خود وارد سیستم شوند. همچنین شانس ایجاد حساب های تکراری در سرویس شما توسط کاربران را کاهش می دهد.

ورود به حساب پیوندی به عنوان بخشی از جریان ورود به سیستم با یک ضربه برای Android در دسترس است. این بدان معناست که اگر برنامه شما قبلاً ویژگی One Tap را فعال کرده باشد، نیازی به وارد کردن کتابخانه جداگانه ندارید.

در این سند، یاد خواهید گرفت که چگونه برنامه اندروید خود را برای پشتیبانی از ورود به حساب پیوندی تغییر دهید.

چگونه کار می کند

  1. در طول جریان ورود به سیستم با یک ضربه، نمایش حساب‌های مرتبط را انتخاب می‌کنید.
  2. اگر کاربر در Google وارد شده است و حساب Google خود را با حساب خود در سرویس شما مرتبط کرده است، ما یک کد شناسه برای حساب پیوند شده برای شما ارسال می کنیم.
  3. به کاربر یک درخواست ورود به سیستم با یک ضربه با گزینه ای برای ورود به سرویس شما با حساب مرتبط خود نشان داده می شود.
  4. اگر کاربر بخواهد با حساب پیوند شده ادامه دهد، رمز شناسه کاربر به برنامه شما برگردانده می‌شود. شما این را با توکنی که در مرحله 2 برای شناسایی کاربر وارد شده به سرور شما ارسال شده است مطابقت دهید.

برپایی

محیط توسعه خود را تنظیم کنید

جدیدترین خدمات Google Play را در میزبان توسعه خود دریافت کنید:

  1. Android SDK Manager را باز کنید.
  1. در زیر ابزار SDK ، خدمات Google Play را پیدا کنید.

  2. اگر وضعیت این بسته‌ها نصب نشده است، هر دو را انتخاب کنید و روی Install Packages کلیک کنید.

برنامه خود را پیکربندی کنید

  1. در فایل build.gradle در سطح پروژه خود، مخزن Maven Google را در هر دو بخش buildscript و allprojects قرار دهید.

    buildscript {
        repositories {
            google()
        }
    }
    
    allprojects {
        repositories {
            google()
        }
    }
    
  2. وابستگی های مربوط به API "Link with Google" را به فایل gradle سطح برنامه ماژول خود اضافه کنید، که معمولا app/build.gradle است:

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

برنامه Android خود را تغییر دهید تا از ورود به حساب پیوندی پشتیبانی کند

در پایان جریان ورود به حساب پیوندی، یک رمز شناسه به برنامه شما برگردانده می شود. یکپارچگی رمز شناسه باید قبل از ورود کاربر تأیید شود.

نمونه کد زیر مراحل بازیابی، تأیید شناسه رمز و متعاقباً ورود کاربر را شرح می دهد.

  1. یک فعالیت برای دریافت نتیجه هدف ورود به سیستم ایجاد کنید

    کاتلین

      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”)
        }
      }
    

    جاوا

      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. درخواست ثبت نام را بسازید

    کاتلین

    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()
    

    جاوا

     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 را اجرا کنید

    کاتلین

     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)
      }
    

    جاوا

     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);
    });
    

یکپارچگی شناسه رمز را بررسی کنید

To verify that the token is valid, ensure that the following criteria are satisfied:

  • The ID token is properly signed by Google. Use Google's public keys (available in JWK or PEM format) to verify the token's signature. These keys are regularly rotated; examine the Cache-Control header in the response to determine when you should retrieve them again.
  • The value of aud in the ID token is equal to one of your app's client IDs. This check is necessary to prevent ID tokens issued to a malicious app being used to access data about the same user on your app's backend server.
  • The value of iss in the ID token is equal to accounts.google.com or https://accounts.google.com.
  • The expiry time (exp) of the ID token has not passed.
  • If you want to restrict access to only members of your G Suite domain, verify that the ID token has an hd claim that matches your G Suite domain name.

Rather than writing your own code to perform these verification steps, we strongly recommend using a Google API client library for your platform, or a general-purpose JWT library. For development and debugging, you can call our tokeninfo validation endpoint.

استفاده از Google API Client Library

استفاده از Java Google API Client Library روشی توصیه شده برای تایید اعتبار توکن های Google ID در محیط تولید است.

جاوا

  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 آنها را تأیید می‌کند.

اگر می‌خواهید دسترسی فقط به اعضای دامنه G Suite خود را محدود کنید، با بررسی نام دامنه بازگردانده شده با روش Payload.getHostedDomain() ادعای hd را نیز تأیید کنید.

تماس با نقطه پایانی tokeninfo

یک راه آسان برای تأیید اعتبار امضای رمز شناسه برای اشکال‌زدایی ، استفاده از نقطه پایانی tokeninfo است. فراخوانی این نقطه پایانی شامل یک درخواست شبکه اضافی است که بیشتر اعتبارسنجی را برای شما انجام می دهد، در حالی که شما اعتبارسنجی مناسب و استخراج محموله را در کد خود آزمایش می کنید. برای استفاده در کد تولید مناسب نیست زیرا ممکن است درخواست‌ها کاهش یابد یا در معرض خطاهای متناوب قرار گیرند.

برای تأیید اعتبار یک نشانه شناسه با استفاده از نقطه پایانی tokeninfo ، یک درخواست HTTPS POST یا GET به نقطه پایانی ارسال کنید و رمز ID خود را در پارامتر id_token ارسال کنید. به عنوان مثال، برای تأیید اعتبار رمز XYZ123، درخواست GET زیر را انجام دهید:

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

اگر توکن به درستی امضا شده باشد و ادعاهای iss و exp مقادیر مورد انتظار را داشته باشند، یک پاسخ HTTP 200 دریافت خواهید کرد که در آن بدنه شامل ادعاهای رمز ID با فرمت 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"
}

اگر مشتری G Suite هستید، ممکن است به ادعای hd نیز علاقه مند باشید که دامنه میزبانی کاربر را نشان می دهد. این می تواند برای محدود کردن دسترسی به یک منبع فقط به اعضای دامنه های خاص استفاده شود. عدم وجود این ادعا نشان می دهد که کاربر به دامنه میزبانی شده G Suite تعلق ندارد.