使用穿戴式裝置進行驗證

Wear OS 可在沒有隨附應用程式的情況下獨立執行,表示 Wear OS 應用程式在存取網際網路資料時,需要自行管理驗證方式。但手錶的螢幕尺寸較小,輸入功能也較不完善,因此 Wear OS 應用程式能夠使用的驗證方式有限。

本指南說明 Wear OS 應用程式的建議驗證方法,以及這些方法不適合應用程式用途時的替代選項。

如要進一步瞭解如何設計良好的登入體驗,請參閱登入使用者體驗指南

訪客模式

請勿採用一律要求驗證的做法,而是要讓使用者在不須登入的情況下盡可能使用更多功能。

使用者可能會在未使用行動應用程式的情況下,探索並安裝您的 Wear 應用程式,因此他們可能沒有帳戶,也可能不知道其中提供了哪些功能。確認訪客模式功能正確展示應用程式的各項功能。

推薦的驗證方法

請用以下的驗證方法,讓 Wear OS 應用程式得以獨立取得使用者的驗證憑證。

透過資料層傳遞權杖

透過 Wearable Data Layer,手機隨附應用程式可以安全將驗證資料傳送到 Wear OS 應用程式。以訊息或資料項目形式傳送憑證。

這種驗證方式通常不需要使用者採取任何行動。不過請您避免在不通知使用者要登入的情況下進行驗證。您可以用簡潔並可以關閉的螢幕告知使用者瞭解手機正在傳送帳戶。

重要事項:這種驗證方式僅限和 Android 配對的手錶使用,且需安裝對應的行動應用程式,因此您的 Wear 應用程式必須提供至少任一種其他的驗證方法。請為沒有對應手機應用程式的使用者,或是和 iOS 裝置配對的 Wear OS 裝置使用者考慮,並提供替代驗證方式。

請透過資料層從手機應用程式傳遞權杖,如以下範例所示:

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 Data Layer,請參閱「在 Wear OS 上傳送資料和進行同步處理」。

使用 OAuth 2.0

Wear OS 支援兩項 OAuth 2.0 流程,詳情請參閱以下各節:

  • RFC 7636 中定義,使用 Proof Key for Code Exchange (PKCE) 授予授權碼
  • RFC 8628 中定義,授予裝置授權。

注意:為了協助確保應用程式不會在手錶進入微光模式時關閉,請在執行驗證程序的活動中使用 AmbientModeSupport.attach,以便啟用「一律開啟」設定。如果想進一步瞭解微光模式最佳做法,請參閱「在 Wear 上讓應用程式持續顯示」。

Proof Key for Code Exchange (PKCE)

如果想有效利用 PKCE,請用 RemoteAuthClient

為了讓 Wear OS 應用程式向 OAuth 提供者執行驗證要求,請建立 OAuthRequest 物件。這個物件內有取得權杖用的 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 error
        }
    }
)

這項要求會向隨附應用程式觸發呼叫,然後用使用者的手機網路瀏覽器顯示驗證 UI。Auth 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 將回應轉發給第三方手錶應用程式。

此時,手錶應用程式即可用授權碼交換存取權杖。

注意事項:建構 OAuthRequest 之後,您可以藉由存取 redirectUrl 找到重新導向網址。

裝置授權

使用「裝置授權」時,使用者會在另一台裝置上開啟驗證 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 API 控制台專案,並自行建立 Android Studio 專案,然後才能在 Wear OS 應用程式中整合 Google 登入。詳情請參閱「 開始將 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 Sign-In 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);

The user is prompted to select a Google account to sign in with. If you requested scopes beyond profile, email, and open ID, the user is also prompted to grant access to those resources.

Finally, in the activity's onActivityResult method, retrieve the sign-in result with getSignInResultFromIntent. After you retrieve the sign-in result, you can check whether the sign-in succeeded using the isSuccess method. If sign-in succeeds, you can call the getSignInAccount method to get a GoogleSignInAccount object that contains information about the signed-in user, such as the user's name. These steps are shown in the following example:

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 的「 Android Wear Google 登入範例」。

自訂程式碼驗證

除了前述驗證方法之外,您還可以要求使用者透過其他裝置 (例如手機或平板電腦) 進行驗證,並取得時效短暫的數字代碼。隨後,使用者只要在 Wear OS 裝置上輸入該代碼,即可確認自己的身分並收到驗證權杖。

這個驗證流程可以使用應用程式的登入模組,或者手動將第三方驗證服務供應商登入方式整合至應用程式的程式碼。雖然這種驗證方法必須手動操作和多花一番心力,但是也因此更加安全,如果您的獨立 Wear OS 應用程式需要提早進行驗證,便可使用此方法。

這項設定的驗證流程如下:

  1. 使用者在需要驗證的 Wear OS 應用程式上執行動作。
  2. Wear OS 應用程式會顯示驗證畫面,並指示使用者輸入來自特定網址的代碼。
  3. 使用者切換到行動裝置、平板電腦或電腦,然後開啟瀏覽器並前往 Wear OS 應用程式指定的網址並登入。
  4. 使用者會收到一組時效短暫的數字代碼,然後使用 Wear OS 內附的鍵盤將此代碼輸入 Wear OS 應用程式驗證畫面:

  5. 之後,您便可以用這組輸入的代碼證明使用者身分無誤,然後用這組代碼交換儲存於 Wear OS 裝置上的驗證權杖,以便驗證呼叫繼續傳遞下去。

注意:使用者產生的程式碼必須為純數字,不得包含任何字母字元。

這個驗證流程如下圖所示: