אפליקציות Wear OS יכולות לפעול באופן עצמאי, ללא אפליקציה נלווית. כלומר, אפליקציית Wear OS צריכה לנהל את האימות בעצמה כשהיא ניגשת לנתונים מהאינטרנט. עם זאת, גודל המסך הקטן של השעון ויכולות הקלט המוגבלות מגבילות את אפשרויות האימות שבהן אפליקציה ל-Wear OS יכולה להשתמש.
במדריך הזה מפורטות ההוראות לשיטת האימות המומלצת לאפליקציות ל-Wear OS, Credential Manager.
למידע נוסף על עיצוב חוויית כניסה טובה, אפשר לעיין במדריך בנושא חוויית משתמש בכניסה.
שיקולים ראשוניים
לפני שמתחילים בהטמעה, כדאי להביא בחשבון את הנקודות הבאות.
מצב אורח
לא דורשים אימות לכל הפונקציונליות. במקום זאת, כדאי לספק למשתמשים כמה שיותר תכונות בלי לדרוש מהם להיכנס לחשבון.
משתמשים עשויים למצוא ולהתקין את האפליקציה שלכם ל-Wear בלי להשתמש באפליקציה לנייד, ולכן יכול להיות שאין להם חשבון ואולי הם לא יודעים אילו תכונות היא מציעה. חשוב לוודא שהפונקציונליות של מצב האורח מציגה בצורה מדויקת את התכונות של האפליקציה.
יכול להיות שחלק מהמכשירים יישארו נעולים למשך זמן ארוך יותר
במכשירים נתמכים עם Wear OS 5 ואילך, המערכת מזהה אם המשתמש עונד את המכשיר על פרק כף היד. אם המשתמש משבית את זיהוי פרק כף היד ואז מסיר את המכשיר מהפרק, המערכת שומרת על ביטול הנעילה של המכשיר למשך זמן ארוך יותר מאשר במקרה אחר.
אם באפליקציה שלכם נדרש רמה גבוהה יותר של אבטחה – למשל, כשמוצגים נתונים רגישים או פרטיים – תחילה צריך לבדוק אם זיהוי פרק כף היד מופעל:
val wristDetectionEnabled =
isWristDetectionAutoLockingEnabled(applicationContext)
אם ערך ההחזרה של השיטה הזו הוא false
, צריך לבקש מהמשתמש להיכנס לחשבון באפליקציה לפני שמוצג תוכן ספציפי למשתמש.
מנהל פרטי הכניסה
Credential Manager הוא ה-API המומלץ לאימות ב-Wear OS. היא מספקת סביבה מאובטחת יותר שמאפשרת למשתמשים להיכנס לאפליקציות של Wear OS בסביבה עצמאית, בלי צורך בטלפון מחובר ומתאימים ולא צריך לזכור את הסיסמה.
במסמך הזה מפורט המידע שמפתחים צריכים כדי להטמיע פתרון של Credential Manager עם מנגנוני האימות הרגילים שהוא מארח, שהם:
- מפתחות גישה
- סיסמאות
- זהויות מאוחדות (כמו 'כניסה באמצעות חשבון Google')
במדריך הזה מוסבר גם איך להעביר את שיטות האימות האחרות הקבילות ל-Wear OS (שיתוף אסימונים בשכבת הנתונים ו-OAuth) כגיבויים ל-Credential Manager, וגם הוראות מיוחדות לטיפול במעבר מהלחצן העצמאי 'כניסה באמצעות חשבון Google' (שעבר עכשיו לשימוש מוגבל) לגרסה המוטמעת של Credential Manager.
מפתחות גישה ב-Wear OS
מומלץ מאוד למפתחים להטמיע מפתחות גישה בהטמעות של מנהל פרטי הכניסה של Wear OS. מפתחות גישה הם התקן החדש בתחום לאימות של משתמשי קצה, והם מציעים למשתמשים כמה יתרונות משמעותיים.
מפתחות גישה הם נוחים יותר
- המשתמשים יכולים לבחור חשבון שבו הם רוצים להיכנס. הם לא צריכים להקליד שם משתמש.
- המשתמשים יכולים לבצע אימות באמצעות השיטה לביטול נעילת המסך במכשיר.
- אחרי שיוצרים ומרשמים מפתח גישה, המשתמש יכול לעבור בצורה חלקה למכשיר חדש ולהשתמש בו באופן מיידי בלי צורך להירשם מחדש.
מפתחות גישה בטוחים יותר
- המפתחים שומרים בשרת רק מפתח ציבורי במקום סיסמה, כך שגורם זדוני לא יכול להפיק הרבה ערך מפריצה לשרתים, וגם קל יותר לנקות את השרתי במקרה של פריצה.
- מפתחות גישה מספקים הגנה מפני פישינג. מפתחות הגישה פועלים רק באתרים ובאפליקציות שבהם הם רשומים. אי אפשר להטעות משתמשים ולגרום להם לבצע אימות באתר מטעה, כי הדפדפן או מערכת ההפעלה מטפלים באימות.
- מפתחות גישה מפחיתים את הצורך בשליחת הודעות SMS, וכך מאפשרים לבצע אימות בצורה חסכונית יותר.
הטמעת מפתחות גישה
כולל הגדרה והנחיות לכל סוגי ההטמעה.
הגדרה
מגדירים את רמת ה-API לטירגוט כ-35 בקובץ build.gradle של מודול האפליקציה:
android { defaultConfig { targetSdkVersion(35) } }
מוסיפים את השורות הבאות לקובץ build.gradle של האפליקציה או המודול, באמצעות הגרסה היציבה האחרונה מהמקור
androidx.credentials
releases.androidx.credentials:credentials:1.5.0 androidx.credentials:credentials-play-services-auth:1.5.0
שיטות אימות מובנות
מאחר ש-Credential Manager הוא ממשק API מאוחד, שלבי ההטמעה ב-Wear OS זהים לאלה של כל סוג מכשיר אחר.
תוכלו להיעזר בהוראות לנייד כדי להתחיל להשתמש במפתחות גישה ובתמיכה בסיסמה.
השלבים להוספת תמיכה בכניסה באמצעות חשבון Google ל-Credential Manager מיועדים לפיתוח לנייד, אבל הם זהים גם ב-Wear OS. בקטע מעבר מהגרסה הקודמת של 'כניסה באמצעות חשבון Google' מפורטות הנחיות מיוחדות למקרה כזה.
חשוב לזכור: אי אפשר ליצור פרטי כניסה ב-Wear OS, ולכן אין צורך להטמיע את השיטות ליצירת פרטי כניסה שמפורטות בהוראות לנייד.
שיטות אימות לגיבוי
יש עוד שתי שיטות אימות מקובלות לאפליקציות ל-Wear OS: OAuth 2.0 (בכל אחת מהגרסאות) ושיתוף שכבת הנתונים של אסימון האימות לנייד. למרות שלשיטות האלה אין נקודות שילוב ב-Credential Manager API, אפשר לכלול אותן בתהליך חוויית המשתמש של Credential Manager כחלופות במקרה שהמשתמשים סוגרים את המסך של Credential Manager.
כדי לטפל בפעולה של המשתמש לסגירת המסך של מנהל פרטי הכניסה, צריך לזהות את האירוע NoCredentialException
כחלק מהלוגיקה של GetCredential
ולנווט לממשק המשתמש המותאם אישית של האימות.
yourCoroutineScope.launch {
try {
val response = credentialManager.getCredential(activity, request)
signInWithCredential(response.credential)
} catch (e: GetCredentialCancellationException) {
navigateToFallbackAuthMethods()
}
}
לאחר מכן, ממשק המשתמש המותאם אישית לאימות יוכל לספק כל אחת משיטות האימות הקבילות האחרות שמתוארות במדריך לגבי חוויית המשתמש של כניסה לחשבון.
שיתוף אסימונים של שכבת הנתונים
אפליקציית התלווה לטלפון יכולה להעביר נתוני אימות לאפליקציה ל-Wear OS בצורה מאובטחת באמצעות Wearable Data Layer API. העברת פרטי הכניסה כהודעות או כפריטי נתונים.
בדרך כלל לא נדרשת כל פעולה מצד המשתמש כדי לבצע אימות כזה. עם זאת, חשוב להימנע מאימות בלי להודיע למשתמש שהוא נכנס לחשבון. אתם יכולים להודיע למשתמש באמצעות מסך שאפשר לסגור, שבו מוצגת ההודעה שהחשבון שלו מועבר מהנייד.
חשוב: באפליקציה ל-Wear OS צריכה להיות לפחות שיטת אימות אחת נוספת, כי האפשרות הזו פועלת רק בשעונים מותאמים ל-Android כשהאפליקציה לנייד המתאימה מותקנת. לספק שיטת אימות חלופית למשתמשים שאין להם את האפליקציה לנייד המתאימה, או שהמכשיר שלהם עם Wear OS מותאם למכשיר iOS.
העברת אסימונים באמצעות שכבת הנתונים מהאפליקציה לנייד, כפי שמתואר בדוגמה הבאה:
val token = "..." // Auth token to transmit to the Wear OS device.
val dataClient: DataClient = Wearable.getDataClient(context)
val putDataReq: PutDataRequest = PutDataMapRequest.create("/auth").run {
dataMap.putString("token", token)
asPutDataRequest()
}
val putDataTask: Task<DataItem> = dataClient.putDataItem(putDataReq)
להאזין לאירועי שינוי נתונים באפליקציית Wear OS, כפי שמתואר בדוגמה הבאה:
val dataClient: DataClient = Wearable.getDataClient(context)
dataClient.addListener{ dataEvents ->
dataEvents.forEach { event ->
if (event.type == DataEvent.TYPE_CHANGED) {
val dataItemPath = event.dataItem.uri.path ?: ""
if (dataItemPath.startsWith("/auth")) {
val token = DataMapItem.fromDataItem(event.dataItem).dataMap.getString("token")
// Display an interstitial screen to notify the user that
// they're being signed in.
// Then, store the token and use it in network requests.
}
}
}
}
למידע נוסף על השימוש בשכבת הנתונים של Wear OS, ראו שליחת נתונים וסנכרון שלהם ב-Wear OS.
שימוש ב-OAuth 2.0
ב-Wear OS יש תמיכה בשני תהליכים שמבוססים על OAuth 2.0, שמפורטים בהמשך:
- הענקת קוד הרשאה עם מפתח הוכחה להחלפת קוד (PKCE), כפי שמוגדר ב-RFC 7636
- הרשאת גישה למכשיר (DAG), כפי שמוגדרת ב-RFC 8628
מפתח הוכחה לחילופי קודים (PKCE)
כדי להשתמש ב-PKCE בצורה יעילה, צריך להשתמש ב-RemoteAuthClient
.
לאחר מכן, כדי לבצע בקשת אימות מאפליקציית Wear OS לספק OAuth, יוצרים אובייקט OAuthRequest
. האובייקט הזה מורכב מכתובת URL של נקודת הקצה של OAuth לקבלת אסימון ומאובייקט CodeChallenge
.
הקוד הבא מציג דוגמה ליצירת בקשת אימות:
val request = OAuthRequest.Builder(this.applicationContext)
.setAuthProviderUrl(Uri.parse("https://...."))
.setClientId(clientId)
.setCodeChallenge(codeChallenge)
.build()
אחרי שיוצרים את בקשת האימות, שולחים אותה לאפליקציה הנלווית באמצעות השיטה sendAuthorizationRequest()
:
val client = RemoteAuthClient.create(this)
client.sendAuthorizationRequest(request,
{ command -> command?.run() },
object : RemoteAuthClient.Callback() {
override fun onAuthorizationResponse(
request: OAuthRequest,
response: OAuthResponse
) {
// Extract the token from the response, store it, and use it in
// network requests.
}
override fun onAuthorizationError(errorCode: Int) {
// Handle any errors.
}
}
)
הבקשה הזו מפעילה קריאה לאפליקציית האפליקציה, שמציגה לאחר מכן ממשק משתמש להרשאה בדפדפן אינטרנט בטלפון הנייד של המשתמש. ספק OAuth 2.0 מאמת את המשתמש ומקבל ממנו הסכמה להרשאות המבוקשות. התשובה נשלחת לכתובת ה-URL להפניה אוטומטית שנוצרה.
אחרי הרשאה מוצלחת או כושלת, שרת OAuth 2.0 מפנה לכתובת ה-URL שצוינה בבקשה. אם המשתמש יאשר את בקשת הגישה, התשובה תכלול קוד הרשאה. אם המשתמש לא יאשר את הבקשה, התשובה תכלול הודעת שגיאה.
התשובה היא מחרוזת שאילתה, והיא נראית כמו אחת מהדוגמאות הבאות:
https://wear.googleapis.com/3p_auth/com.your.package.name?code=xyz
https://wear.googleapis-cn.com/3p_auth/com.your.package.name?code=xyz
הפעולה הזו טוענת דף שמפנה את המשתמש לאפליקציה הנלווית. האפליקציה הנלווית מאמתת את כתובת ה-URL של התגובה ומעבירה את התגובה לאפליקציה שלכם ל-Wear OS באמצעות ה-API onAuthorizationResponse
.
לאחר מכן, אפליקציית השעון יכולה להחליף את קוד ההרשאה באסימון גישה.
הענקת הרשאה למכשיר
כשמשתמשים בהרשאת הרשאה למכשיר, המשתמש פותח את ה-URI לאימות במכשיר אחר. לאחר מכן, שרת ההרשאות מבקש מהם לאשר או לדחות את הבקשה.
כדי להקל על התהליך, אפשר להשתמש ב-RemoteActivityHelper
כדי לפתוח דף אינטרנט במכשיר הנייד המותאם של המשתמש, כמו בדוגמה הבאה:
// Request access from the authorization server and receive Device Authorization
// Response.
val verificationUri = "..." // Extracted from the Device Authorization Response.
RemoteActivityHelper.startRemoteActivity(
this,
Intent(Intent.ACTION_VIEW)
.addCategory(Intent.CATEGORY_BROWSABLE)
.setData(Uri.parse(verificationUri)),
null
)
// Poll the authorization server to find out if the user completed the user
// authorization step on their mobile device.
אם יש לכם אפליקציה ל-iOS, השתמשו בקישורים אוניברסליים כדי ליירט את הכוונה הזו באפליקציה במקום להסתמך על הדפדפן כדי לאשר את האסימון.
מעבר מהגרסה הקודמת של הכניסה באמצעות חשבון Google
ל-Credential Manager יש נקודת שילוב ייעודית לכפתור 'כניסה באמצעות חשבון Google'. בעבר אפשר היה להוסיף את הלחצן הזה בכל מקום בממשק המשתמש של אימות האפליקציה, אבל עכשיו, אחרי שהוא צורף ל-Credential Manager, האפשרות הישנה הוצאה משימוש.
// Define a basic SDK check.
fun isCredentialManagerAvailable(): Boolean {
return android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.VANILLA_ICE_CREAM
}
// Elsewhere in the code, use it to selectively disable the legacy option.
Button(
onClick = {
if (isCredentialManagerAvailable()) {
Log.w(TAG, "Devices on API level 35 or higher should use
Credential Manager for Sign in with Google")
} else {
navigateToSignInWithGoogle()
}},
enabled = !isCredentialManagerAvailable(),
label = { Text(text = stringResource(R.string.sign_in_with_google)) },
secondaryLabel = { Text(text = "Disabled on API level 35+")
}
)