האפשרות 'כניסה לחשבון מקושר' מאפשרת למשתמשים להשתמש בכניסה בלחיצה אחת באמצעות Google שכבר מקושר לחשבון Google שלהם לשירות שלכם. זה משפר את עבור המשתמשים, כי הם יכולים להיכנס בלחיצה אחת, בלי להזין אותם מחדש שם המשתמש והסיסמה שלהם. כמו כן, הוא מפחית את הסיכויים שמשתמשים חשבונות כפולים בשירות שלכם.
הכניסה לחשבון המקושר זמינה כחלק מתהליך הכניסה בהקשה אחת עבור Android. כלומר, אין צורך לייבא ספרייה נפרדת אם האפליקציה התכונה 'הקשה אחת' כבר מופעלת.
במסמך הזה נסביר איך לשנות את אפליקציית Android כך שתתמוך כניסה לחשבון מקושר.
איך זה עובד
- הבעת הסכמה להצגת חשבונות מקושרים בתהליך הכניסה בהקשה אחת.
- אם המשתמש נכנס לחשבון Google וקישר את חשבון Google שלו אל את החשבון שלו בשירות שלכם, יוחזר אסימון מזהה עבור חשבון.
- מוצגת למשתמש הודעת כניסה בהקשה אחת עם אפשרות להיכנס השירות לחשבון המקושר שלהם.
- אם המשתמש בוחר להמשיך עם החשבון המקושר, האסימון המזהה שלו מוחזר לאפליקציה. את ההתאמה הזו שייכת לאסימון שנשלח אל השרת בשלב 2 כדי לזהות את המשתמש המחובר.
הגדרה
הגדרת סביבת הפיתוח
אפשר לקבל את הגרסה העדכנית ביותר של Google Play Services אצל מארח הפיתוח:
- פותחים את מנהל ה-SDK של Android.
בקטע SDK Tools, מאתרים את Google Play Services.
אם הסטטוס של החבילות האלה הוא 'לא מותקן', בחר את שתי החבילות ולוחצים על Install Pacakge (התקנת חבילות).
הגדרת האפליקציה
בקובץ
build.gradle
ברמת הפרויקט, כוללים את מאגר Maven של Google בקטעbuildscript
וגם בקטעallprojects
.buildscript { repositories { google() } } allprojects { repositories { google() } }
מוסיפים את יחסי התלות של 'Link with Google' אל ה-API של המודול שלך קובץ GRid ברמת האפליקציה, שהוא בדרך כלל
app/build.gradle
:dependencies { implementation 'com.google.android.gms:play-services-auth:21.2.0' }
שינוי האפליקציה ל-Android כך שתתמוך בכניסה לחשבון מקושר
בסיום תהליך הכניסה לחשבון המקושר, אסימון מזהה מוחזר אל אפליקציה. צריך לאמת את התקינות של האסימון המזהה לפני שמכניסים את המשתמש לחשבון.
דוגמת הקוד הבאה מפרטת את השלבים שיש לאחזר, לאמת את האסימון המזהה, ולאחר מכן כניסה לחשבון.
צריך ליצור פעילות כדי לקבל את התוצאה של כוונת הכניסה
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") } });
יצירה של בקשת הכניסה
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()
הפעלה של 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. שימוש במפתחות הציבוריים של Google
(זמין ב:
JWK או
פורמט PEM)
כדי לאמת את החתימה של האסימון. המפתחות האלה עוברים רוטציה באופן קבוע. בדיקה
הכותרת
Cache-Control
בתגובה כדי לקבוע מתי צריך לאחזר אותן שוב. - הערך של
aud
באסימון המזהה שווה לאחד מהערכים של האפליקציה מזהי לקוח. הבדיקה הזו נחוצה כדי למנוע אסימונים מזהים שהונפקו על ידי תוכנה זדונית שמשמשות לגישה לנתונים על אותו משתמש בשרת הקצה העורפי של האפליקציה. - הערך של
iss
באסימון המזהה שווה ל-accounts.google.com
אוhttps://accounts.google.com
. - מועד התפוגה (
exp
) של האסימון המזהה לא עבר. - אם אתם צריכים לאמת שהאסימון המזהה מייצג Google Workspace או Cloud
חשבון ארגוני, אפשר לבדוק את ההצהרה
hd
, שמציינת את המארח הדומיין של המשתמש. צריך להשתמש באפשרות הזו כשמגבילים את הגישה למשאב רק לחברים בדומיין דומיינים מסוימים. היעדר תביעה זו מצביע על כך שהחשבון לא שייך דומיין באירוח Google.
באמצעות השדות email
, email_verified
ו-hd
אפשר לקבוע אם
Google מארחת כתובת אימייל מסוימת, והיא מהימן. במקרים שבהם Google היא גורם מוסמך,
ידוע שהמשתמש הוא הבעלים החוקיים של החשבון, תוכל לדלג על הזנת סיסמה
שיטות לאתגר.
מקרים שבהם Google היא מהימן:
- ל-
email
יש סיומת@gmail.com
. זהו חשבון Gmail. email_verified
מוגדר כ-True ו-hd
מוגדר. זהו חשבון G Suite.
משתמשים יכולים להירשם לחשבונות Google בלי להשתמש ב-Gmail או ב-G Suite. מתי
email
לא מכיל סיומת @gmail.com
ו-hd
חסר, Google אינה
מומלץ לאמת סיסמה או סיסמה או שיטות אחרות לאימות
למשתמש. email_verified
יכול להיות גם נכון כי Google אימתה בהתחלה את
משתמש כשחשבון 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.");
}
ה-method GoogleIdTokenVerifier.verify()
מאמתת את חתימת ה-JWT,
הצהרת הבעלות על aud
, התלונה על הפרת זכויות יוצרים iss
והצהרת הבעלות על exp
.
אם אתם צריכים לאמת שהאסימון המזהה מייצג Google Workspace או Cloud
חשבון ארגוני, אפשר לאמת את הצהרת הזמן לתפוגה hd
על ידי בדיקת שם הדומיין
שהוחזרו באמצעות השיטה Payload.getHostedDomain()
.
קריאה לנקודת הקצה של Tokeninfo
דרך קלה לאמת חתימה של אסימון מזהה לצורך ניפוי באגים היא
משתמשים בנקודת הקצה tokeninfo
. קריאה לנקודת הקצה הזו כוללת
בקשת רשת נוספת שמבצעת את רוב האימות עבורכם בזמן שאתם בודקים
אימות וחילוץ מטען ייעודי (payload) בקוד שלכם. הוא לא מתאים לשימוש בסביבת ייצור
יכול להיות שבקשות עשויות להיות מווסתות או מושפעות משגיאות המתרחשות לסירוגין.
כדי לאמת אסימון מזהה באמצעות נקודת הקצה 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.