可穿戴设备上的身份验证

关键词:wear,用户,auth

Wear OS 应用可以独立运行,无需配套应用。这意味着 Wear OS 应用需要自行管理身份验证才能访问互联网数据。但是,手表的屏幕尺寸较小,输入能力有限,这限制了 Wear OS 应用可以使用身份验证选项。

本指南介绍了 Wear OS 应用推荐的身份验证方法,以及在这些方法不适合应用用例时的替代方法。

要了解有关如何设计良好的登录体验的更多信息,请查看 登录 UX 指南

访客模式

不要为所有功能都要求身份验证。相反,尽可能向用户提供尽可能多的功能,而无需他们登录。

用户可能会在未使用移动应用的情况下发现并安装您的 Wear 应用,因此他们可能没有帐户,也可能不知道该应用提供哪些功能。确保访客模式功能准确地展示了您的应用功能。

某些设备的解锁时间可能会更长

在运行 Wear OS 5 或更高版本的受支持设备上,系统会检测用户是否将设备戴在手腕上。如果用户关闭手腕检测,然后将设备从手腕上取下,则系统会将设备保持解锁状态的时间比其他情况更长。

如果您的应用需要更高的安全级别(例如,在显示潜在敏感或私人数据时),请首先检查是否启用了手腕检测。

val wristDetectionEnabled =
        isWristDetectionAutoLockingEnabled(applicationContext)

如果此方法的返回值为false,请提示用户在显示用户特定内容之前登录您的应用中的帐户。

推荐的身份验证方法

使用以下身份验证方法,使独立 Wear OS 应用能够获取用户身份验证凭据。

使用数据层传递令牌

手机配套应用可以使用 Wearable 数据层安全地将身份验证数据传输到 Wear OS 应用。将凭据作为消息或数据项传输。

这种类型的身份验证通常不需要用户执行任何操作。但是,避免在未告知用户正在登录的情况下执行身份验证。您可以使用简单的、可关闭的屏幕来告知用户他们的帐户正在从移动设备传输。

重要提示:您的 Wear 应用必须至少提供另一种身份验证方法,因为此选项仅在安装了相应移动应用的 Android 配对手表上有效。为没有相应移动应用或其 Wear OS 设备与 iOS 设备配对的用户提供备用身份验证方法。

从移动应用使用数据层传递令牌,如下例所示

val token = "..." // Auth token to transmit to the wearable 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)

按照以下示例监听手表应用上的数据更改事件

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 interstitial screen to notify the user they are being signed in.
                // Then, store the token and use it in network requests.
            }
        }
    }
}

有关使用 Wearable 数据层的更多信息,请参阅在 Wear OS 上发送和同步数据

使用 OAuth 2.0

Wear OS 支持两种基于 OAuth 2.0 的流程,如下节所述

  • 带有代码交换证明密钥 (PKCE) 的授权码授予,如RFC 7636中所定义
  • 设备授权授予,如RFC 8628中所定义

注意:为确保您的应用在手表进入环境模式时不会关闭,请使用执行身份验证的活动中的AmbientModeSupport.attach启用始终开启模式。有关环境模式最佳实践的更多信息,请参阅保持您的应用在 Wear 上可见

代码交换证明密钥 (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 error
        }
    }
)

此请求会触发对配套应用的调用,然后配套应用会在用户的手机上的网络浏览器中显示授权 UI。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,并使用onAuthorizationResponse API 将响应转发到第三方手表应用。

然后,手表应用可以将授权码交换为访问令牌。

注意:构建OAuthRequest后,您可以通过访问redirectUrl来查找您的重定向 URL。

设备授权授予

使用设备授权授予时,用户会在另一台设备上打开验证 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 应用,请使用通用链接来拦截您的应用中的此意图,而不是依赖浏览器来授权令牌。

其他身份验证方法

Wear OS 支持其他登录方法,如下节所述。

Google 登录

Google 登录允许用户使用其现有的 Google 帐户登录。它提供了最佳的用户体验,并且易于支持,尤其是在您已经在手持式应用中实现它时。

在前面介绍的推荐身份验证方法之后,Google 登录是下一个首选解决方案,因为它在 iOS 上也能很好地工作。以下部分介绍如何完成基本的 Google 登录集成。

先决条件

在开始将 Google 登录集成到您的 Wear OS 应用之前,您必须配置 Google API 控制台项目并设置您的 Android Studio 项目。有关更多信息,请参阅开始将 Google 登录集成到您的 Android 应用中

如果您将 Google 登录与与后端服务器通信的应用或网站一起使用,则还有两个额外的先决条件

  • 为您的后端服务器创建一个 OAuth 2.0 网络应用程序客户端 ID。此客户端 ID 与您的应用的客户端 ID 不同。有关更多信息,请参阅启用服务器端访问
  • 通过使用 HTTPS 发送用户的 ID 令牌,安全地识别服务器上当前登录的用户。要了解如何在后端服务器上验证您的用户,请参阅使用后端服务器进行身份验证

将 Google 登录集成到您的应用中

查看并实施以下步骤(在以下部分中详细介绍),以将 Google 登录集成到您的 Wear OS 应用中

  1. 配置 Google 登录.
  2. 添加 Google 登录按钮.
  3. 点击登录按钮时启动登录流程.

配置 Google 登录并构建 GoogleApiClient 对象

在您的登录活动的onCreate()方法中,配置 Google 登录以请求您的应用所需的用户数据。然后,创建一个具有对 Google 登录 API 和您指定的选项的访问权限的GoogleApiClient对象。以下示例显示了这些步骤

public class MyNewActivity extends AppCompatActivity {

    private static final int RC_SIGN_IN = 9001;

    private GoogleSignInClient mSignInClient;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        GoogleSignInOptions options =
                new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
                        .build();

        mSignInClient = GoogleSignIn.getClient(this, options);
    }
}

向您的应用添加 Google 登录按钮

完成以下步骤以添加 Google 登录按钮

  1. SignInButton添加到您的应用的布局中
  2.  <com.google.android.gms.common.SignInButton
     android:id="@+id/sign_in_button"
     android:layout_width="wrap_content"
     android:layout_height="wrap_content" />
  3. 在您的应用的onCreate()方法中,注册按钮的OnClickListener,以便在点击时登录用户
  4. Kotlin

    findViewById<View>(R.id.sign_in_button).setOnClickListener(this)

    Java

    findViewById(R.id.sign_in_button).setOnClickListener(this);

创建登录意图并启动登录流程

通过使用 getSignInIntent()方法创建登录意图,在您的onCLick()方法中处理登录按钮点击。然后使用 startActivityForResult()方法启动意图。

Intent intent = mSignInClient.getSignInIntent();
startActivityForResult(intent, RC_SIGN_IN);

系统会提示用户选择一个 Google 帐户登录。如果您请求的范围超出了个人资料、电子邮件和开放 ID,还会提示用户授予对这些资源的访问权限。

最后,在活动的 onActivityResult方法中,使用 getSignInResultFromIntent检索登录结果。检索登录结果后,您可以使用 isSuccess方法检查登录是否成功。如果登录成功,您可以调用 getSignInAccount方法来获取一个 GoogleSignInAccount对象,其中包含有关登录用户的信息,例如用户的姓名。以下示例显示了这些步骤

Kotlin

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent) {
    super.onActivityResult(requestCode, resultCode, data)

    // Result returned from launching the Intent from GoogleSignInApi.getSignInIntent(...).
    if (requestCode == RC_SIGN_IN) {
        Auth.GoogleSignInApi.getSignInResultFromIntent(data)?.apply {
            if (isSuccess) {
                // Get account information.
                fullName = signInAccount?.displayName
                mGivenName = signInAccount?.givenName
                mFamilyName = signInAccount?.familyName
                mEmail = signInAccount?.email
            }
        }
    }
}

Java

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);

    // Result returned from launching the Intent from GoogleSignInApi.getSignInIntent(...).
    if (requestCode == RC_SIGN_IN) {
        GoogleSignInResult signInResult = Auth.GoogleSignInApi.getSignInResultFromIntent(data);
        if (signInResult.isSuccess()) {
            GoogleSignInAccount acct = signInResult.getSignInAccount();

            // Get account information.
            fullName = acct.getDisplayName();
            givenName = acct.getGivenName();
            familyName = acct.getFamilyName();
            email = acct.getEmail();
        }
    }
}

要查看实现 Google 登录的示例应用,请参阅 GitHub 上的Horologist Google 登录示例

自定义代码身份验证

作为前面介绍的身份验证方法的替代方法,您可以要求用户从其他设备(例如手机或平板电脑)进行身份验证,并获得一个短期数字代码。然后,用户在其 Wear OS 设备上输入代码以确认其身份,并接收身份验证令牌。

此身份验证流程使用您的应用的登录模块,或手动将第三方身份验证提供程序登录方法集成到您的应用代码中。尽管此身份验证方法需要手动操作和额外的工作才能使其更安全,但如果您需要在独立 Wear OS 应用中尽早进行身份验证,则可以使用此方法。

此设置的身份验证流程如下所示

  1. 用户执行需要授权的 Wear OS 应用操作。
  2. Wear OS 应用向用户显示身份验证屏幕,并指示用户从指定的 URL 输入代码。
  3. 用户切换到移动设备、平板电脑或 PC,然后启动浏览器,导航到 Wear OS 应用上指定的 URL 并登录。
  4. 用户会收到一个短期数字代码,他们可以使用 Wear OS 中的内置键盘将其输入到 Wear OS 应用身份验证屏幕中

  5. 从这一点开始,您可以使用输入的代码作为证明这是正确用户的证据,并将代码交换为存储在 Wear OS 设备上并用于以后进行身份验证调用的身份验证令牌。

注意:用户生成的代码**必须纯粹是数字的**,不能包含任何字母字符。

此身份验证流程如下图所示