Wear OS 应用可以独立运行,无需配套应用。这意味着 Wear OS 应用在访问互联网数据时需要自行管理身份验证。但手表的屏幕尺寸较小,输入功能有限,这限制了 Wear OS 应用可用的身份验证选项。
本指南提供了 Wear OS 应用的推荐身份验证方法“凭据管理器”的说明。
要详细了解如何设计良好的登录体验,请参阅登录用户体验指南。
前期注意事项
在开始实施之前,请考虑以下几点。
访客模式
不要对所有功能都要求身份验证。相反,应尽可能向用户提供无需登录即可使用的功能。
用户可能会在未使用移动应用的情况下发现并安装您的 Wear 应用,因此他们可能没有帐号,也可能不知道应用提供哪些功能。请确保访客模式功能能够准确展示您应用的功能。
某些设备可能解锁时间更长
在搭载 Wear OS 5 或更高版本的受支持设备上,系统会检测用户是否佩戴设备在手腕上。如果用户关闭手腕检测,然后从手腕上取下设备,系统将比正常情况下更长时间地保持设备解锁。
如果您的应用需要更高级别的安全性(例如在显示可能敏感或私密的数据时),请先检查是否启用了手腕检测
val wristDetectionEnabled =
isWristDetectionAutoLockingEnabled(applicationContext)
如果此方法的返回值为 false
,请在显示用户特定内容之前提示用户登录您应用中的帐号。
凭据管理器
凭据管理器是 Wear OS 上推荐的身份验证 API。它提供了一个更安全的环境,让用户可以在独立设置中登录 Wear OS 应用,而无需连接配对的手机,也无需记住密码。
本文档概述了开发者需要了解的信息,以便使用凭据管理器中包含的标准身份验证机制实现凭据管理器解决方案,这些机制包括
- 密钥
- 密码
- 联合身份(例如“使用 Google 帐号登录”)
本指南还提供了如何迁移其他可接受的 Wear OS 身份验证方法(数据层令牌共享和OAuth)作为凭据管理器的备份,以及处理从现已弃用的独立 Google 登录按钮到嵌入式凭据管理器版本的特殊说明。
Wear OS 上的密钥
强烈建议开发者在其 Wear OS 凭据管理器实现中实施密钥。密钥是面向最终用户的身份验证新行业标准,它们为用户带来了多项重要的优势。
密钥更简单
- 用户可以选择一个帐号登录。他们无需输入用户名。
- 用户可以使用设备的屏幕锁定进行身份验证。
- 密钥创建并注册后,用户可以无缝切换到新设备并立即使用,无需重新注册。
密钥更安全
- 开发者只需将公钥保存到服务器,而不是保存密码,这意味着恶意行为者入侵服务器的价值大大降低,并且在发生数据泄露时需要清理的工作也大大减少。
- 密钥提供防网络钓鱼保护。密钥仅在其注册的网站和应用上有效;用户不会被诱骗在欺骗性网站上进行身份验证,因为浏览器或操作系统会处理验证。
- 密钥减少了发送短信的需求,使身份验证更具成本效益。
实现密钥
包括所有实现类型的设置和指南。
设置
在应用模块的 build.gradle 文件中将目标 API 级别设置为 35
android { defaultConfig { targetSdkVersion(35) } }
使用
androidx.credentials
版本参考中的最新稳定版本,将以下行添加到您的应用或模块的 build.gradle 文件中。androidx.credentials:credentials:1.5.0 androidx.credentials:credentials-play-services-auth:1.5.0
内置身份验证方法
由于凭据管理器是一个统一的 API,因此 Wear OS 的实现步骤与其他任何设备类型都相同。
使用移动端说明开始并实现密钥和密码支持。
将“使用 Google 帐号登录”支持添加到凭据管理器的步骤是针对移动开发的,但在 Wear OS 上这些步骤是相同的。请参阅弃用旧版“使用 Google 帐号登录”一节,了解本用例的特殊注意事项。
请注意,由于无法在 Wear OS 上创建凭据,因此您无需实现移动说明中提到的凭据创建方法。
备用身份验证方法
Wear OS 应用还有两种其他可接受的身份验证方法:OAuth 2.0(任一变体)和移动身份验证令牌数据层共享。虽然这些方法在凭据管理器 API 中没有集成点,但它们可以作为备用方法包含在您的凭据管理器 UX 流程中,以防用户关闭凭据管理器屏幕。
为处理用户关闭凭据管理器屏幕的操作,请在您的GetCredential
逻辑中捕获NoCredentialException
,然后导航到您自己的自定义身份验证界面。
yourCoroutineScope.launch {
try {
val response = credentialManager.getCredential(activity, request)
signInWithCredential(response.credential)
} catch (e: GetCredentialCancellationException) {
navigateToFallbackAuthMethods()
}
}
然后,您的自定义身份验证界面可以提供登录用户体验指南中描述的任何其他可接受的身份验证方法。
数据层令牌共享
手机配套应用可以使用 Wearable Data Layer API 将身份验证数据安全地传输到 Wear OS 应用。将凭据作为消息或数据项进行传输。
这种身份验证类型通常不需要用户执行任何操作。但是,请避免在未通知用户已登录的情况下执行身份验证。您可以使用可关闭的屏幕告知用户其帐号正在从移动设备传输。
重要提示:您的 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.
}
}
}
}
如需详细了解如何使用 Wearable Data Layer,请参阅在 Wear OS 上发送和同步数据。
使用 OAuth 2.0
Wear OS 支持两种基于 OAuth 2.0 的流程,如下文所述
代码交换证明密钥 (PKCE)
为有效使用 PKCE,请使用RemoteAuthClient
。然后,要从您的 Wear OS 应用向 OAuth 提供方执行身份验证请求,请创建OAuthRequest
对象。此对象包含指向您的 OAuth 端点(用于获取令牌)的 URL 和一个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 提供方会验证用户身份并获取用户对所请求权限的同意。响应会发送到自动生成的重定向网址。
成功或失败授权后,OAuth 2.0 服务器会将用户重定向到请求中指定的网址。如果用户批准访问请求,则响应包含授权码。如果用户未批准请求,则响应包含错误消息。
响应采用查询字符串的形式,示例如下
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
这会加载一个页面,将用户定向到配套应用。配套应用会验证响应网址并使用 onAuthorizationResponse
API 将响应中继到您的 Wear OS 应用。
然后,手表应用可以将授权码换成访问令牌。
设备授权授予
使用设备授权授予时,用户会在另一台设备上打开验证 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 应用,请使用通用链接来在您的应用中拦截此 intent,而不是依赖浏览器来授权令牌。
弃用旧版“使用 Google 帐号登录”
凭据管理器有一个专门用于“使用 Google 帐号登录”按钮的集成点。以前,此按钮可以添加到应用身份验证用户体验的任何位置,但随着它包含在凭据管理器中,旧选项现已弃用。
// 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+")
}
)