אימות משתמשים באמצעות כניסה באמצעות חשבון Google

התחברות באמצעות חשבון Google עוזרת לכם לשלב במהירות אימות משתמשים באפליקציית Android שלכם. המשתמשים יכולים להשתמש בחשבון Google שלהם כדי להיכנס לאפליקציה, לתת הסכמה ולשתף בצורה מאובטחת את פרטי הפרופיל שלהם עם האפליקציה. ספריית Credential Manager Jetpack של Android מאפשרת שילוב חלק, ומציעה חוויה עקבית במכשירי Android באמצעות API יחיד.

במאמר הזה מוסבר איך להטמיע כניסה באמצעות חשבון 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. לוחצים על Create client.
    3. בוחרים בסוג האפליקציה Android.
  4. בקטע , יוצרים Client-ID חדש מסוג 'אפליקציית אינטרנט' אם עוד לא עשיתם זאת. בינתיים אפשר להתעלם מהשדות Authorized JavaScript Origins (מקורות JavaScript מורשים) ו-Authorized redirect URIs (כתובות URI מורשות להפניה אוטומטית). מזהה הלקוח הזה ישמש לזיהוי שרת הקצה העורפי שלכם כשהוא מתקשר עם שירותי האימות של Google.
    1. עוברים אל .
    2. לוחצים על Create client.
    3. בוחרים בסוג Web application.

הצהרה על יחסי תלות

בקובץ 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()

קודם כול, בודקים אם למשתמש יש חשבונות ששימשו בעבר לכניסה לאפליקציה שלכם. לשם כך, קוראים ל-API עם הפרמטר setFilterByAuthorizedAccounts שמוגדר לערך true. המשתמשים יכולים לבחור מבין החשבונות הזמינים כדי להיכנס.

אם אין חשבונות Google מורשים זמינים, המשתמש יתבקש להירשם באמצעות אחד מהחשבונות הזמינים שלו. כדי לעשות זאת, צריך להציג למשתמש בקשה על ידי קריאה חוזרת ל-API והגדרת 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. אחרי שה-API יפעל בהצלחה, צריך לחלץ את 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', כדאי לבצע אופטימיזציה של האפליקציה למילוי אוטומטי. אחרי שהמשתמש יוצר חשבון, מומלץ לרשום אותו למפתחות גישה כשלב אחרון בתהליך יצירת החשבון.

טיפול ביציאה מהחשבון

כשמשתמש מתנתק מהאפליקציה, צריך להפעיל את שיטת ה-API‏ clearCredentialState() כדי לנקות את מצב פרטי הכניסה הנוכחיים של המשתמש מכל ספקי פרטי הכניסה. הפעולה הזו תשלח הודעה לכל ספקי האישורים שצריך למחוק את כל סשן האישורים שמאוחסן עבור האפליקציה הנתונה.

יכול להיות שספק פרטי הכניסה שמר סשן פעיל של פרטי כניסה, וישתמש בו כדי להגביל את אפשרויות הכניסה לקריאות get-credential עתידיות. לדוגמה, יכול להיות שהמערכת תיתן עדיפות לפרטי הכניסה הפעילים על פני פרטי כניסה אחרים שזמינים. כשהמשתמש יוצא מהאפליקציה באופן מפורש, כדי לקבל את אפשרויות הכניסה ההוליסטיות בפעם הבאה, צריך לקרוא ל-API הזה כדי לאפשר לספק לנקות את סשן האישורים המאוחסנים.