Xác thực trên thiết bị đeo

Các ứng dụng Wear OS có thể chạy độc lập mà không cần có ứng dụng đồng hành. Tức là một ứng dụng Wear OS cần phải tự quản lý quy trình xác thực khi truy cập vào dữ liệu qua Internet. Nhưng kích thước màn hình nhỏ của đồng hồ và khả năng nhập liệu hạn chế làm giới hạn cách thức xác thực mà một ứng dụng Wear OS có thể sử dụng.

Hướng dẫn này đề cập đến các phương thức xác thực được đề xuất cho ứng dụng Wear OS, cũng như các phương án thay thế khi những phương thức đó không phù hợp với trường hợp sử dụng của ứng dụng.

Để tìm hiểu thêm về cách thiết kế trải nghiệm đăng nhập tiện lợi, hãy xem Hướng dẫn về trải nghiệm người dùng đăng nhập.

Chế độ khách

Đừng yêu cầu xác thực cho mọi chức năng. Thay vào đó, hãy cung cấp cho người dùng nhiều tính năng nhất có thể mà không yêu cầu họ đăng nhập.

Có thể người dùng khám phá và cài đặt ứng dụng Wear của bạn mà không dùng ứng dụng di động. Vì vậy, họ có thể không có tài khoản và không biết những tính năng của ứng dụng đó. Hãy đảm bảo rằng chức năng của chế độ khách thể hiện chính xác các tính năng của ứng dụng.

Một số thiết bị có thể ở trạng thái mở khoá lâu hơn

Trên các thiết bị được hỗ trợ chạy Wear OS 5 trở lên, hệ thống sẽ phát hiện xem người dùng có đeo thiết bị trên cổ tay hay không. Nếu người dùng tắt tính năng phát hiện cổ tay rồi tháo thiết bị khỏi cổ tay, thì hệ thống sẽ giữ cho thiết bị ở trạng thái mở khoá lâu hơn so với bình thường.

Nếu ứng dụng của bạn yêu cầu mức độ bảo mật cao hơn (chẳng hạn như khi hiển thị dữ liệu có thể nhạy cảm hoặc riêng tư), trước tiên, hãy kiểm tra xem tính năng phát hiện cổ tay có được bật hay không:

val wristDetectionEnabled =
        isWristDetectionAutoLockingEnabled(applicationContext)

Nếu giá trị trả về của phương thức này là false, hãy nhắc người dùng đăng nhập vào một tài khoản trong ứng dụng của bạn trước khi hiển thị nội dung dành riêng cho người dùng.

Phương thức xác thực được đề xuất

Hãy sử dụng những phương thức xác thực sau để cho phép các ứng dụng Wear OS độc lập lấy thông tin xác thực của người dùng.

Truyền mã thông báo bằng lớp dữ liệu

Ứng dụng đồng hành cho điện thoại có thể chuyển dữ liệu xác thực đến ứng dụng Wear OS một cách an toàn bằng cách sử dụng Lớp dữ liệu cho thiết bị đeo. Chuyển thông tin xác thực dưới dạng thông báo hoặc các mục dữ liệu.

Phương thức xác thực này thường không yêu cầu người dùng làm gì cả. Tuy nhiên, hãy tránh xác thực mà không thông báo cho người dùng về việc họ đang đăng nhập. Bạn có thể thông báo cho người dùng bằng một màn hình đơn giản có thể đóng được, cho họ thấy tài khoản của họ đang được chuyển từ thiết bị di động sang.

Lưu ý quan trọng: Ứng dụng Wear của bạn phải cung cấp ít nhất một phương thức xác thực khác, vì lựa chọn này chỉ hoạt động trên các đồng hồ được ghép nối với Android khi ứng dụng di động tương ứng được cài đặt. Hãy cung cấp phương thức xác thực thay thế cho những người dùng không có ứng dụng di động tương ứng hoặc có thiết bị Wear OS được ghép nối với thiết bị iOS.

Truyền mã thông báo bằng lớp dữ liệu trong ứng dụng di động như minh hoạ trong ví dụ sau:

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)

Theo dõi các sự kiện thay đổi dữ liệu trên ứng dụng đồng hồ như minh hoạ trong ví dụ sau:

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.
            }
        }
    }
}

Để biết thêm thông tin về cách sử dụng Lớp dữ liệu trên thiết bị đeo, hãy xem bài viết Gửi và đồng bộ hoá dữ liệu trên Wear OS.

Sử dụng OAuth 2.0

Wear OS hỗ trợ 2 luồng dựa trên OAuth 2.0 như được mô tả trong các phần sau:

  • Cấp mã uỷ quyền bằng Khoá bằng chứng để trao đổi mã (PKCE) theo mô tả trong RFC 7636
  • Cấp quyền cho thiết bị theo mô tả trong RFC 8628

Lưu ý: Để đảm bảo ứng dụng không bị tắt khi đồng hồ chuyển sang chế độ môi trường xung quanh, hãy bật chế độ Luôn bật bằng cách sử dụng AmbientModeSupport.attach trong hoạt động tiến hành việc xác thực. Để biết thêm thông tin về các phương pháp hay nhất đối với Chế độ môi trường xung quanh, hãy xem bài viết Duy trì sự xuất hiện của ứng dụng trên Wear.

Khoá bằng chứng để trao đổi mã (PKCE)

Để sử dụng PKCE hiệu quả, hãy sử dụng RemoteAuthClient.

Để thực hiện yêu cầu xác thực từ ứng dụng Wear OS tới một trình cung cấp OAuth, hãy tạo một đối tượng OAuthRequest. Đối tượng này bao gồm một URL đến điểm cuối của OAuth để lấy mã thông báo và đối tượng CodeChallenge. Mã sau đây là ví dụ về cách tạo một yêu cầu xác thực:

val request = OAuthRequest.Builder(this.applicationContext)
    .setAuthProviderUrl(Uri.parse("https://...."))
    .setClientId(clientId)
    .setCodeChallenge(codeChallenge)
    .build()

Sau khi tạo yêu cầu xác thực, hãy gửi yêu cầu đó đến ứng dụng đồng hành bằng cách sử dụng phương thức 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
        }
    }
)

Yêu cầu này kích hoạt một lệnh gọi đến ứng dụng đồng hành, sau đó sẽ hiển thị giao diện người dùng uỷ quyền trong một trình duyệt web trên điện thoại di động của người dùng. Trình cung cấp OAuth 2.0 sẽ xác thực người dùng và xin sự đồng ý của người dùng đối với các quyền được yêu cầu. Phản hồi được gửi đến URL chuyển hướng được tạo tự động.

Sau khi uỷ quyền thành công hoặc không thành công, máy chủ OAuth 2.0 sẽ chuyển hướng đến URL được chỉ định trong yêu cầu. Nếu người dùng phê duyệt yêu cầu truy cập, thì phản hồi sẽ chứa mã uỷ quyền. Nếu người dùng không phê duyệt yêu cầu, thì phản hồi sẽ chứa thông báo lỗi.

Phản hồi có dạng chuỗi truy vấn và giống như một trong các ví dụ sau:

  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

Thao tác này sẽ tải trang để hướng người dùng đến ứng dụng đồng hành. Ứng dụng đồng hành xác minh URL phản hồi và chuyển tiếp phản hồi đến ứng dụng đồng hồ của bên thứ ba bằng cách sử dụng API onAuthorizationResponse.

Sau đó, ứng dụng đồng hồ có thể trao đổi mã uỷ quyền để lấy mã truy cập.

Lưu ý: Sau khi tạo OAuthRequest, bạn có thể tìm thấy URL chuyển hướng bằng cách truy cập vào redirectUrl.

Cấp quyền cho thiết bị

Khi sử dụng tính năng Cấp quyền (uỷ quyền) cho thiết bị, người dùng sẽ mở URI xác minh trên một thiết bị khác. Sau đó, máy chủ uỷ quyền sẽ yêu cầu người dùng phê duyệt hoặc từ chối yêu cầu.

Để giúp quá trình này dễ dàng hơn, hãy sử dụng RemoteActivityHelper để mở một trang web trên thiết bị di động đã ghép nối của người dùng như minh hoạ trong ví dụ sau:

// 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.

Nếu bạn có ứng dụng dành cho iOS, hãy sử dụng đường liên kết phổ quát để chặn ý định này trong ứng dụng của bạn thay vì dựa vào trình duyệt để cấp mã thông báo.

Các phương thức xác thực khác

Wear OS hỗ trợ các phương thức đăng nhập khác như mô tả ở các phần sau.

Đăng nhập bằng Google

Tính năng Đăng nhập bằng Google giúp người dùng đăng nhập bằng Tài khoản Google hiện có. API này mang lại trải nghiệm tốt nhất cho người dùng và dễ hỗ trợ, đặc biệt nếu bạn đã triển khai API này trong các ứng dụng cho thiết bị cầm tay.

Tiếp sau các phương thức xác thực được đề xuất như mô tả trước đó, tính năng Đăng nhập bằng Google là giải pháp ưu tiên tiếp theo vì tính năng này cũng hoạt động tốt trên iOS. Phần sau đây mô tả cách hoàn tất quy trình tích hợp cơ bản đối với tính năng Đăng nhập bằng Google.

Điều kiện tiên quyết

Trước khi có thể bắt đầu tích hợp tính năng Đăng nhập bằng Google vào ứng dụng Wear OS, bạn phải định cấu hình dự án Google API Console và thiết lập dự án Android Studio. Để biết thêm thông tin, hãy xem bài viết Bắt đầu tích hợp tính năng Đăng nhập bằng Google vào ứng dụng Android.

Nếu bạn sử dụng tính năng Đăng nhập bằng Google thông qua một ứng dụng hoặc trang web giao tiếp với một máy chủ phụ trợ, thì sẽ có thêm 2 điều kiện tiên quyết:

  • Tạo mã ứng dụng khách của ứng dụng web OAuth 2.0 cho máy chủ phụ trợ. Mã ứng dụng khách này khác với mã ứng dụng khách của ứng dụng bạn sở hữu. Để biết thêm thông tin, hãy xem bài viết Bật quyền truy cập phía máy chủ.
  • Xác định người dùng hiện đã đăng nhập một cách an toàn trên máy chủ bằng cách gửi mã thông báo nhận dạng của người dùng đó thông qua HTTPS. Để tìm hiểu cách xác thực người dùng trên máy chủ phụ trợ, hãy xem bài viết Xác thực bằng máy chủ phụ trợ.

Tích hợp tính năng Đăng nhập bằng Google vào ứng dụng của bạn

Hãy xem và triển khai các bước sau (được nêu chi tiết trong các phần tiếp theo) để tích hợp tính năng Đăng nhập bằng Google vào ứng dụng Wear OS:

  1. Định cấu hình tính năng Đăng nhập bằng Google.
  2. Thêm nút Đăng nhập bằng Google.
  3. Bắt đầu quy trình đăng nhập khi người dùng nhấn vào nút đăng nhập.

Định cấu hình tính năng Đăng nhập bằng Google và tạo đối tượng GoogleApiClient

Trong phương thức onCreate() của hoạt động đăng nhập, hãy định cấu hình tính năng Đăng nhập bằng Google để yêu cầu dữ liệu người dùng theo yêu cầu của ứng dụng. Sau đó, hãy tạo một đối tượng GoogleApiClient có quyền truy cập vào API Đăng nhập bằng Google và các lựa chọn bạn đã chỉ định. Các bước này được thể hiện trong ví dụ sau:

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);
    }
}

Thêm nút Đăng nhập bằng Google vào ứng dụng của bạn

Hoàn tất các bước sau để thêm nút Đăng nhập bằng Google:

  1. Thêm SignInButton vào bố cục của ứng dụng:
  2.  <com.google.android.gms.common.SignInButton
     android:id="@+id/sign_in_button"
     android:layout_width="wrap_content"
     android:layout_height="wrap_content" />
  3. Trong phương thức onCreate() của ứng dụng, hãy đăng ký OnClickListener của nút để đăng nhập người dùng khi họ nhấn vào nút:
  4. Kotlin

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

    Java

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

Tạo ý định đăng nhập và bắt đầu quy trình đăng nhập

Xử lý các thao tác nhấn vào nút đăng nhập trong phương thức onCLick() bằng cách tạo ý định đăng nhập thông qua phương thức getSignInIntent(). Sau đó, hãy bắt đầu ý định bằng phương thức startActivityForResult().

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

Người dùng sẽ được nhắc chọn một Tài khoản Google để đăng nhập. Nếu bạn đã yêu cầu các phạm vi ngoài hồ sơ, email và mã nhận dạng mở, thì người dùng cũng sẽ được nhắc cấp quyền truy cập vào các tài nguyên đó.

Cuối cùng, trong phương thức onActivityResult của hoạt động, hãy truy xuất kết quả đăng nhập bằng getSignInResultFromIntent. Sau khi truy xuất kết quả đăng nhập, bạn có thể kiểm tra xem quy trình đăng nhập có thành công hay không bằng cách sử dụng phương thức isSuccess. Nếu đăng nhập thành công, bạn có thể gọi phương thức getSignInAccount để lấy đối tượng GoogleSignInAccount chứa thông tin về người dùng đã đăng nhập, chẳng hạn như tên của người dùng đó. Các bước này được thể hiện trong ví dụ sau đây:

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();
        }
    }
}

Để xem một ứng dụng mẫu triển khai tính năng Đăng nhập bằng Google, hãy xem Mẫu Đăng nhập bằng Google cho Horologist trên GitHub.

Xác thực mã tuỳ chỉnh

Thay vì các phương thức xác thực được mô tả trước đó, bạn có thể yêu cầu người dùng xác thực từ một thiết bị khác, chẳng hạn như điện thoại di động hoặc máy tính bảng, đồng thời lấy một mã số ngắn hạn. Sau đó, người dùng nhập mã này vào thiết bị Wear OS của họ để xác nhận danh tính và nhận mã thông báo xác thực.

Quy trình xác thực này sử dụng mô-đun đăng nhập của ứng dụng hoặc tích hợp phương thức đăng nhập của nhà cung cấp dịch vụ xác thực bên thứ ba vào mã của ứng dụng theo cách thủ công. Mặc dù phương thức xác thực này yêu cầu thực hiện theo cách thủ công và mất thêm công sức để tăng cường tính bảo mật, nhưng bạn có thể dùng phương thức này nếu cần xác thực sớm trong các ứng dụng Wear OS độc lập.

Quy trình xác thực cho cách thiết lập này hoạt động như sau:

  1. Người dùng thực hiện một thao tác cần được cho phép với ứng dụng Wear OS.
  2. Ứng dụng Wear OS hiển thị một màn hình xác thực cho người dùng và hướng dẫn người dùng nhập mã qua một URL được chỉ định.
  3. Người dùng chuyển sang một thiết bị di động, máy tính bảng hoặc máy tính, rồi chạy một trình duyệt, sau đó chuyển đến URL được chỉ định trên ứng dụng Wear OS và đăng nhập.
  4. Người dùng sẽ nhận một mã số ngắn hạn mà họ nhập vào màn hình xác thực của ứng dụng Wear OS bằng cách sử dụng bàn phím tích hợp trong Wear OS:

  5. Từ thời điểm này, bạn có thể sử dụng mã đã nhập để làm bằng chứng cho thấy đây đúng là người dùng cần xác thực, đồng thời đổi mã đó lấy mã xác thực được lưu trữ và bảo mật trên thiết bị Wear OS cho các lệnh gọi đã xác thực về sau.

Lưu ý: Mã do người dùng tạo phải hoàn toàn là số và không được chứa bất kỳ ký tự chữ cái nào.

Quy trình xác thực này được mô tả trong biểu đồ sau: