Android FIDO2 API แรกของคุณ

1. บทนำ

FIDO2 API คืออะไร

FIDO2 API ช่วยให้แอปพลิเคชัน Android สามารถสร้างและใช้ข้อมูลรับรองที่ใช้คีย์สาธารณะที่ได้รับการรับรองและรัดกุมเพื่อวัตถุประสงค์ในการตรวจสอบสิทธิ์ผู้ใช้ โดย API นี้มีการใช้งานไคลเอ็นต์ WebAuthn ซึ่งรองรับการใช้ตัวตรวจสอบสิทธิ์การโรมมิ่งผ่าน USB (คีย์ความปลอดภัย) และ BLE, NFC รวมถึงตัวตรวจสอบสิทธิ์แพลตฟอร์ม ซึ่งจะช่วยให้ผู้ใช้ตรวจสอบสิทธิ์โดยใช้ลายนิ้วมือหรือการล็อกหน้าจอ

สิ่งที่คุณจะสร้าง...

ใน Codelab นี้ คุณจะได้สร้างแอป Android ที่มีฟังก์ชันการตรวจสอบสิทธิ์ซ้ำได้ง่ายๆ โดยใช้เซ็นเซอร์ลายนิ้วมือ "การตรวจสอบสิทธิ์ซ้ำ" คือการที่ผู้ใช้ลงชื่อเข้าใช้แอป จากนั้นตรวจสอบสิทธิ์อีกครั้งเมื่อผู้ใช้เปลี่ยนกลับไปใช้แอปของคุณ หรือเมื่อพยายามเข้าถึงส่วนสำคัญของแอป กรณีหลังเรียกอีกอย่างหนึ่งว่า "การตรวจสอบสิทธิ์แบบขั้นตอน"

สิ่งที่คุณจะได้เรียนรู้...

คุณจะได้เรียนรู้วิธีเรียกใช้ Android FIDO2 API และตัวเลือกที่คุณสามารถจัดเตรียมไว้เพื่อตอบสนองโอกาสต่างๆ นอกจากนี้ คุณจะได้ทราบแนวทางปฏิบัติแนะนำในการตรวจสอบสิทธิ์อีกครั้งด้วย

สิ่งที่คุณต้องมี...

  • อุปกรณ์ Android ที่มีเซ็นเซอร์ลายนิ้วมือ (แม้จะไม่มีเซ็นเซอร์ลายนิ้วมือ แต่การล็อกหน้าจอก็ยังมีฟังก์ชันการยืนยันผู้ใช้ที่เทียบเท่ากัน)
  • Android OS 7.0 ขึ้นไปที่มีการอัปเดตล่าสุด อย่าลืมลงทะเบียนลายนิ้วมือ (หรือการล็อกหน้าจอ)

2. การตั้งค่า

โคลนที่เก็บ

ดูที่เก็บ GitHub

https://github.com/android/codelab-fido2

$ git clone https://github.com/android/codelab-fido2.git

เราจะนำอะไรบ้าง

  • อนุญาตให้ผู้ใช้ลงทะเบียน "ผู้ใช้ที่ยืนยันตัวตรวจสอบสิทธิ์แพลตฟอร์ม" (โทรศัพท์ Android ที่มีเซ็นเซอร์ลายนิ้วมือทำหน้าที่เหมือนโทรศัพท์)
  • อนุญาตให้ผู้ใช้ตรวจสอบสิทธิ์ตนเองกับแอปอีกครั้งโดยใช้ลายนิ้วมือ

คุณสามารถดูตัวอย่างสิ่งที่คุณกำลังจะสร้างได้จากที่นี่

เริ่มโปรเจ็กต์ Codelab

แอปที่เสร็จสมบูรณ์แล้วจะส่งคำขอไปยังเซิร์ฟเวอร์ที่ https://webauthn-codelab.glitch.me คุณอาจลองใช้แอปเดียวกันในเวอร์ชันเว็บจากที่นั่น

c2234c42ba8a6ef1.png

คุณกำลังจะทำงานในแอปเวอร์ชันของคุณเอง

  1. ไปที่หน้าแก้ไขของเว็บไซต์ที่ https://glitch.com/edit/#!/webauthn-codelab
  2. ค้นหา "รีมิกซ์เพื่อแก้ไข" ที่มุมบนขวา เมื่อกดปุ่ม คุณจะสามารถ "แยก" โค้ดและดำเนินการต่อโดยใช้เวอร์ชันของคุณเองพร้อมทั้ง URL ของโปรเจ็กต์ใหม่ 9ef108869885e4ce.png
  3. คัดลอกชื่อโปรเจ็กต์ที่ด้านซ้ายบน (คุณจะแก้ไขชื่อโปรเจ็กต์ได้ตามต้องการ) c91d0d59c61021a4.png
  4. วางไปยังส่วน HOSTNAME ของไฟล์ .env ในข้อบกพร่อง 889b55b1cf74b894.png

3. เชื่อมโยงแอปและเว็บไซต์กับลิงก์เนื้อหาดิจิทัล

หากต้องการใช้ FIDO2 API ในแอป Android ให้เชื่อมโยง API กับเว็บไซต์และแชร์ข้อมูลเข้าสู่ระบบระหว่างกัน โดยใช้ลิงก์เนื้อหาดิจิทัล คุณประกาศการเชื่อมโยงได้โดยฝากไฟล์ JSON ของลิงก์เนื้อหาดิจิทัล (Digital Asset Links) ในเว็บไซต์ และเพิ่มลิงก์ไปยังไฟล์ลิงก์เนื้อหาดิจิทัล (Digital Asset Link) ลงในไฟล์ Manifest ของแอป

โฮสต์ .well-known/assetlinks.json ที่โดเมนของคุณ

คุณสามารถระบุการเชื่อมโยงระหว่างแอปกับเว็บไซต์ได้โดยการสร้างไฟล์ JSON และวางไว้ที่ .well-known/assetlinks.json โชคดีที่เรามีโค้ดเซิร์ฟเวอร์ที่แสดงไฟล์ assetlinks.json โดยอัตโนมัติ เพียงแค่เพิ่มพารามิเตอร์สภาพแวดล้อมต่อไปนี้ลงในไฟล์ .env ในข้อบกพร่อง

  • ANDROID_PACKAGENAME: ชื่อแพ็กเกจของแอป (com.example.android.fido2)
  • ANDROID_SHA256HASH: SHA256 แฮชของใบรับรองที่ลงนาม

ใช้คำสั่งด้านล่างเพื่อรับแฮช SHA256 ของใบรับรองที่มีการรับรองนักพัฒนาแอป รหัสผ่านเริ่มต้นของคีย์สโตร์สำหรับการแก้ไขข้อบกพร่องคือ "android"

$ keytool -exportcert -list -v -alias androiddebugkey -keystore ~/.android/debug.keystore

เมื่อเข้าถึง https://<your-project-name>.glitch.me/.well-known/assetlinks.json คุณควรเห็นสตริง JSON เช่นนี้:

[{
  "relation": ["delegate_permission/common.handle_all_urls", "delegate_permission/common.get_login_creds"],
  "target": {
    "namespace": "web",
    "site": "https://<your-project-name>.glitch.me"
  }
}, {
  "relation": ["delegate_permission/common.handle_all_urls", "delegate_permission/common.get_login_creds"],
  "target": {
    "namespace": "android_app",
    "package_name": "com.example.android.fido2",
    "sha256_cert_fingerprints": ["DE:AD:BE:EF:..."]
  }
}]

เปิดโปรเจ็กต์ใน Android Studio

คลิก "เปิดโปรเจ็กต์ Android Studio ที่มีอยู่" บนหน้าจอต้อนรับของ Android Studio

เลือก "Android" ภายในที่เก็บให้ชำระเงิน

1062875cf11ffb95.png

เชื่อมโยงแอปกับรีมิกซ์

เปิดไฟล์ gradle.properties ที่ด้านล่างของไฟล์ ให้เปลี่ยน URL โฮสต์เป็นรีมิกซ์ของ Glitch ที่คุณเพิ่งสร้าง

// ...

# The URL of the server
host=https://<your-project-name>.glitch.me

ในกรณีนี้ การกําหนดค่าลิงก์เนื้อหาดิจิทัล (Digital Asset Links) ควรพร้อมใช้งานแล้ว

4. ดูว่าตอนนี้แอปทำงานอย่างไร

มาเริ่มต้นโดยดูวิธีการทำงานของแอปกันเลย อย่าลืมเลือก "app-start" ในช่องคอมโบการเรียกใช้การกำหนดค่า คลิก "เรียกใช้" (รูปสามเหลี่ยมสีเขียวถัดจากช่องคอมโบ) เพื่อเปิดแอปบนอุปกรณ์แอนดรอยด์ที่เชื่อมต่อของคุณ

29351fb97062b43c.png

เมื่อเปิดแอป คุณจะเห็นหน้าจอให้พิมพ์ชื่อผู้ใช้ นี่คือ UsernameFragment เพื่อวัตถุประสงค์ในการสาธิต แอปและเซิร์ฟเวอร์จะต้องยอมรับชื่อผู้ใช้ เพียงพิมพ์อะไรก็ได้และกด "ถัดไป"

bd9007614a9a3644.png

หน้าจอถัดไปที่คุณเห็นคือ AuthFragment ซึ่งผู้ใช้จะลงชื่อเข้าใช้ด้วยรหัสผ่านได้ เราจะเพิ่มฟีเจอร์สำหรับลงชื่อเข้าใช้ด้วย FIDO2 ที่นี่ในภายหลัง เพื่อวัตถุประสงค์ในการสาธิต แอปและเซิร์ฟเวอร์จะต้องยอมรับรหัสผ่าน เพียงพิมพ์อะไรก็ได้และกด "ลงชื่อเข้าใช้"

d9caba817a0a99bd.png

นี่คือหน้าจอสุดท้ายของแอปนี้ HomeFragment ในตอนนี้คุณจะเห็นเฉพาะรายการข้อมูลเข้าสู่ระบบที่ว่างเปล่าที่นี่เท่านั้น กำลังกด "Reauth" จะพาคุณกลับไปที่ AuthFragment กำลังกด "ออกจากระบบ" จะพาคุณกลับไปที่ UsernameFragment ปุ่มการทำงานแบบลอยที่มีเครื่องหมาย "+" ไม่ได้ดำเนินการใดๆ ในตอนนี้ แต่จะเป็นการเริ่มต้นการลงทะเบียน

การรับรองใหม่เมื่อคุณใช้ขั้นตอนการลงทะเบียน FIDO2

1cfcc6c884020e37.png

มีเทคนิคที่มีประโยชน์ต่อไปนี้ก่อนเริ่มเขียนโค้ด ใน Android Studio ให้กด "TODO" ที่ด้านล่าง ซึ่งจะแสดงรายการสิ่งที่ต้องทำทั้งหมดใน Codelab นี้ เราจะเริ่มด้วยสิ่งที่ต้องทำแรกในส่วนถัดไป

e5a811bbc7cd7b30.png

5. ลงทะเบียนข้อมูลเข้าสู่ระบบโดยใช้ลายนิ้วมือ

หากต้องการเปิดใช้การตรวจสอบสิทธิ์โดยใช้ลายนิ้วมือ ก่อนอื่นคุณจะต้องลงทะเบียนข้อมูลเข้าสู่ระบบที่สร้างโดยผู้ใช้ที่ยืนยันตัวตรวจสอบสิทธิ์แพลตฟอร์ม ซึ่งเป็นตัวตรวจสอบสิทธิ์ที่ฝังในอุปกรณ์ซึ่งจะยืนยันผู้ใช้โดยใช้ข้อมูลไบโอเมตริก เช่น เซ็นเซอร์ลายนิ้วมือ

37ce78fdf2759832.png

ดังที่เราได้เห็นในส่วนก่อนหน้านี้ ตอนนี้ปุ่มการทำงานแบบลอยไม่สามารถดำเนินการใดๆ ได้ มาดูวิธีลงทะเบียนการรับรองใหม่กัน

เรียก API เซิร์ฟเวอร์: /auth/registerRequest

เปิด AuthRepository.kt แล้วค้นหา TODO(1)

ในที่นี้ registerRequest คือเมธอดที่มีการเรียกใช้เมื่อกด FAB เราอยากให้วิธีการนี้เรียก API ของเซิร์ฟเวอร์ /auth/registerRequest API จะแสดงผล ApiResult พร้อม PublicKeyCredentialCreationOptions ทั้งหมดที่ไคลเอ็นต์ต้องใช้ในการสร้างข้อมูลเข้าสู่ระบบใหม่

จากนั้นเราจะโทรหา getRegisterPendingIntent พร้อมตัวเลือกต่างๆ FIDO2 API นี้จะส่งคืน PendingIntent ของ Android เพื่อเปิดกล่องโต้ตอบลายนิ้วมือและสร้างข้อมูลเข้าสู่ระบบใหม่ จากนั้นเราสามารถส่งคืน PendingIntent นั้นไปยังผู้โทรได้

จากนั้นวิธีการจะมีลักษณะดังต่อไปนี้

suspend fun registerRequest(): PendingIntent? {
  fido2ApiClient?.let { client ->
    try {
      val sessionId = dataStore.read(SESSION_ID)!!
      when (val apiResult = api.registerRequest(sessionId)) {
        ApiResult.SignedOutFromServer -> forceSignOut()
        is ApiResult.Success -> {
          if (apiResult.sessionId != null) {
            dataStore.edit { prefs ->
              prefs[SESSION_ID] = apiResult.sessionId
            }
          }
          val task = client.getRegisterPendingIntent(apiResult.data)
          return task.await()
        }
      }
    } catch (e: Exception) {
      Log.e(TAG, "Cannot call registerRequest", e)
    }
  }
  return null
}

เปิดกล่องโต้ตอบลายนิ้วมือสำหรับการลงทะเบียน

เปิด HomeFragment.kt แล้วค้นหา TODO(2)

ซึ่ง UI ได้รับ Intent กลับมาจาก AuthRepository ในที่นี้เราจะใช้สมาชิก createCredentialIntentLauncher ในการเปิดตัว PendingIntent ที่เราได้จากขั้นตอนก่อนหน้า การดำเนินการนี้จะเปิดกล่องโต้ตอบสำหรับการสร้างข้อมูลเข้าสู่ระบบ

binding.add.setOnClickListener {
  lifecycleScope.launch {
    val intent = viewModel.registerRequest()
    if (intent != null) {
      createCredentialIntentLauncher.launch(
        IntentSenderRequest.Builder(intent).build()
      )
    }
  }
}

รับ ActivityResult ด้วยข้อมูลเข้าสู่ระบบใหม่

เปิด HomeFragment.kt แล้วค้นหา TODO(3)

ระบบจะเรียกเมธอด handleCreateCredentialResult นี้หลังจากปิดกล่องโต้ตอบลายนิ้วมือ หากสร้างข้อมูลเข้าสู่ระบบสำเร็จแล้ว สมาชิก data ของ ActivityResult จะมีข้อมูลเข้าสู่ระบบดังกล่าว

ก่อนอื่น เราต้องแยก PublicKeyCredential จาก data Intent ของข้อมูลมีช่องไบต์อาร์เรย์ที่มีคีย์ Fido.FIDO2_KEY_CREDENTIAL_EXTRA คุณสามารถใช้เมธอดแบบคงที่ใน PublicKeyCredential ที่เรียกว่า deserializeFromBytes เพื่อเปลี่ยนไบต์อาร์เรย์เป็นออบเจ็กต์ PublicKeyCredential

ถัดไป ให้ตรวจสอบว่าสมาชิก response ของออบเจ็กต์ข้อมูลเข้าสู่ระบบนี้เป็น AuthenticationErrorResponse หรือไม่ หากใช่ แสดงว่าเกิดข้อผิดพลาดในการสร้างข้อมูลเข้าสู่ระบบ ไม่เช่นนั้น เราจะส่งข้อมูลเข้าสู่ระบบไปยังแบ็กเอนด์ของเราได้

วิธีที่ทำเสร็จแล้วจะมีลักษณะดังนี้

private fun handleCreateCredentialResult(activityResult: ActivityResult) {
  val bytes = activityResult.data?.getByteArrayExtra(Fido.FIDO2_KEY_CREDENTIAL_EXTRA)
  when {
    activityResult.resultCode != Activity.RESULT_OK ->
      Toast.makeText(requireContext(), R.string.cancelled, Toast.LENGTH_LONG).show()
    bytes == null ->
      Toast.makeText(requireContext(), R.string.credential_error, Toast.LENGTH_LONG)
        .show()
    else -> {
      val credential = PublicKeyCredential.deserializeFromBytes(bytes)
      val response = credential.response
      if (response is AuthenticatorErrorResponse) {
        Toast.makeText(requireContext(), response.errorMessage, Toast.LENGTH_LONG)
          .show()
      } else {
        viewModel.registerResponse(credential)
      }
    }
  }
}

เรียก API เซิร์ฟเวอร์: /auth/registerResponse

เปิด AuthRepository.kt แล้วค้นหา TODO(4)

ระบบจะเรียกเมธอด registerResponse นี้หลังจากที่ UI สร้างข้อมูลเข้าสู่ระบบใหม่เรียบร้อยแล้ว และเราต้องการส่งกลับไปยังเซิร์ฟเวอร์

ออบเจ็กต์ PublicKeyCredential มีข้อมูลเกี่ยวกับข้อมูลเข้าสู่ระบบที่สร้างขึ้นใหม่ด้านใน ตอนนี้เราต้องการจำรหัสของคีย์ภายในเพื่อให้แตกต่างจากคีย์อื่นๆ ที่ลงทะเบียนไว้ในเซิร์ฟเวอร์ ในออบเจ็กต์ PublicKeyCredential ให้นำพร็อพเพอร์ตี้ rawId ของรายการดังกล่าวไปใส่ในตัวแปรสตริงในเครื่องโดยใช้ toBase64

ตอนนี้เราพร้อมที่จะส่งข้อมูลไปยังเซิร์ฟเวอร์แล้ว ใช้ api.registerResponse เพื่อเรียกใช้ API ของเซิร์ฟเวอร์และส่งการตอบกลับ ค่าที่ส่งคืนจะมีรายการข้อมูลเข้าสู่ระบบทั้งหมดที่ลงทะเบียนบนเซิร์ฟเวอร์ ซึ่งรวมถึงข้อมูลเข้าสู่ระบบใหม่

สุดท้าย เราบันทึกผลลัพธ์ใน DataStore ได้ ควรบันทึกรายการข้อมูลเข้าสู่ระบบพร้อมกับคีย์ CREDENTIALS เป็น StringSet คุณสามารถใช้ toStringSet เพื่อแปลงรายการข้อมูลเข้าสู่ระบบเป็น StringSet

นอกจากนี้ เราได้บันทึกรหัสข้อมูลเข้าสู่ระบบด้วยคีย์ LOCAL_CREDENTIAL_ID

suspend fun registerResponse(credential: PublicKeyCredential) {
  try {
    val sessionId = dataStore.read(SESSION_ID)!!
    val credentialId = credential.rawId.toBase64()
    when (val result = api.registerResponse(sessionId, credential)) {
      ApiResult.SignedOutFromServer -> forceSignOut()
      is ApiResult.Success -> {
        dataStore.edit { prefs ->
          result.sessionId?.let { prefs[SESSION_ID] = it }
          prefs[CREDENTIALS] = result.data.toStringSet()
          prefs[LOCAL_CREDENTIAL_ID] = credentialId
        }
      }
    }
  } catch (e: ApiException) {
    Log.e(TAG, "Cannot call registerResponse", e)
  }
}

เรียกใช้แอป แล้วคุณจะสามารถคลิกที่ FAB และลงทะเบียนข้อมูลเข้าสู่ระบบใหม่ได้

7d64d9289c5a3cbc.png

6. ตรวจสอบสิทธิ์ผู้ใช้ด้วยลายนิ้วมือ

ตอนนี้เรามีข้อมูลเข้าสู่ระบบที่ลงทะเบียนบนแอปและเซิร์ฟเวอร์ ตอนนี้เราสามารถให้ผู้ใช้ลงชื่อเข้าใช้ได้แล้ว เรากำลังเพิ่มฟีเจอร์การลงชื่อเข้าใช้ด้วยลายนิ้วมือใน AuthFragment เมื่อผู้ใช้มาถึงแล้ว ระบบจะแสดงกล่องโต้ตอบลายนิ้วมือ เมื่อการตรวจสอบสิทธิ์สำเร็จ ระบบจะเปลี่ยนเส้นทางผู้ใช้ไปยัง HomeFragment

เรียก API เซิร์ฟเวอร์: /auth/signinRequest

เปิด AuthRepository.kt แล้วค้นหา TODO(5)

ระบบจะเรียกเมธอด signinRequest นี้เมื่อเปิด AuthFragment เราต้องการเซิร์ฟเวอร์และพิจารณาว่าจะอนุญาตให้ผู้ใช้ลงชื่อเข้าใช้ด้วย FIDO2 ได้หรือไม่

ก่อนอื่น เราต้องเรียก PublicKeyCredentialRequestOptions จากเซิร์ฟเวอร์ ใช้ api.signInRequest เพื่อเรียกใช้ API ของเซิร์ฟเวอร์ ApiResult ที่แสดงผลมี PublicKeyCredentialRequestOptions

เมื่อใช้ PublicKeyCredentialRequestOptions เราสามารถใช้ FIDO2 API getSignIntent เพื่อสร้าง PendingIntent เพื่อเปิดกล่องโต้ตอบลายนิ้วมือได้

สุดท้าย เราสามารถส่งคืน PendingIntent กลับไปยัง UI ได้

suspend fun signinRequest(): PendingIntent? {
  fido2ApiClient?.let { client ->
    val sessionId = dataStore.read(SESSION_ID)!!
    val credentialId = dataStore.read(LOCAL_CREDENTIAL_ID)
    if (credentialId != null) {
      when (val apiResult = api.signinRequest(sessionId, credentialId)) {
        ApiResult.SignedOutFromServer -> forceSignOut()
        is ApiResult.Success -> {
          val task = client.getSignPendingIntent(apiResult.data)
          return task.await()
        }
      }
    }
  }
  return null
}

เปิดกล่องโต้ตอบลายนิ้วมือเพื่อยืนยัน

เปิด AuthFragment.kt แล้วค้นหา TODO(6)

ซึ่งก็เหมือนกับขั้นตอนการลงทะเบียนของเรา เราสามารถเปิดกล่องโต้ตอบลายนิ้วมือที่มีสมาชิก signIntentLauncher ได้

viewLifecycleOwner.lifecycleScope.launchWhenStarted {
  launch {
    viewModel.signinRequests.collect { intent ->
      signIntentLauncher.launch(
        IntentSenderRequest.Builder(intent).build()
      )
    }
  }
  launch {
    ...
  }
}

จัดการกิจกรรมผลลัพธ์

เปิด AuthFragment.kt แล้วค้นหา TODO(7)

ซึ่งก็เหมือนกับที่เราทำกับการลงทะเบียน เราสามารถดึงข้อมูล PublicKeyCredential ตรวจหาข้อผิดพลาด และส่งไปยัง ViewModel ได้

private fun handleSignResult(activityResult: ActivityResult) {
  val bytes = activityResult.data?.getByteArrayExtra(Fido.FIDO2_KEY_CREDENTIAL_EXTRA)
  when {
    activityResult.resultCode != Activity.RESULT_OK ->
      Toast.makeText(requireContext(), R.string.cancelled, Toast.LENGTH_SHORT).show()
    bytes == null ->
      Toast.makeText(requireContext(), R.string.auth_error, Toast.LENGTH_SHORT)
        .show()
    else -> {
      val credential = PublicKeyCredential.deserializeFromBytes(bytes)
      val response = credential.response
      if (response is AuthenticatorErrorResponse) {
        Toast.makeText(requireContext(), response.errorMessage, Toast.LENGTH_SHORT)
          .show()
      } else {
        viewModel.signinResponse(credential)
      }
    }
  }
}

เรียก API เซิร์ฟเวอร์: /auth/signinResponse

เปิด AuthRepository.kt แล้วค้นหา TODO(8)

ออบเจ็กต์ PublicKeyCredential มีรหัสข้อมูลเข้าสู่ระบบอยู่ในฐานะ keyHandle มาบันทึกค่านี้ในตัวแปรสตริงในเครื่องเพื่อเก็บไว้ใช้ทีหลังเหมือนที่เราทำในขั้นตอนการลงทะเบียน

ตอนนี้เราพร้อมที่จะเรียก API เซิร์ฟเวอร์ด้วย api.signinResponse แล้ว ค่าที่แสดงผลประกอบด้วยรายการข้อมูลเข้าสู่ระบบ

ณ จุดนี้การลงชื่อเข้าใช้เสร็จสมบูรณ์แล้ว เราต้องจัดเก็บผลลัพธ์ทั้งหมดใน DataStore ควรจัดเก็บรายการข้อมูลเข้าสู่ระบบเป็น StringSet โดยใช้คีย์ CREDENTIALS รหัสข้อมูลเข้าสู่ระบบในเครื่องที่เราบันทึกไว้ข้างต้นควรจัดเก็บเป็นสตริงที่มีคีย์ LOCAL_CREDENTIAL_ID

สุดท้าย เราต้องอัปเดตสถานะการลงชื่อเข้าใช้เพื่อให้ UI เปลี่ยนเส้นทางผู้ใช้ไปยัง HomeFragment ได้ ซึ่งทำได้โดยการปล่อยออบเจ็กต์ SignInState.SignedIn ไปยัง SharedFlow ที่ชื่อ signInStateMutable นอกจากนี้ เรายังต้องการเรียกใช้ refreshCredentials เพื่อดึงข้อมูลเข้าสู่ระบบของผู้ใช้ด้วย เพื่อให้ผู้ใช้เหล่านั้นแสดงใน UI ด้วย

suspend fun signinResponse(credential: PublicKeyCredential) {
  try {
    val username = dataStore.read(USERNAME)!!
    val sessionId = dataStore.read(SESSION_ID)!!
    val credentialId = credential.rawId.toBase64()
    when (val result = api.signinResponse(sessionId, credential)) {
      ApiResult.SignedOutFromServer -> forceSignOut()
      is ApiResult.Success -> {
        dataStore.edit { prefs ->
          result.sessionId?.let { prefs[SESSION_ID] = it }
          prefs[CREDENTIALS] = result.data.toStringSet()
          prefs[LOCAL_CREDENTIAL_ID] = credentialId
        }
        signInStateMutable.emit(SignInState.SignedIn(username))
        refreshCredentials()
      }
    }
  } catch (e: ApiException) {
    Log.e(TAG, "Cannot call registerResponse", e)
  }
}

เรียกใช้แอปและคลิก "Reauth" เพื่อเปิด AuthFragment ตอนนี้คุณควรเห็นกล่องโต้ตอบลายนิ้วมือที่แจ้งให้คุณลงชื่อเข้าใช้ด้วยลายนิ้วมือ

45f81419f84952c8.png

ยินดีด้วย ตอนนี้คุณก็ได้เรียนรู้วิธีใช้ FIDO2 API บน Android เพื่อลงทะเบียนและลงชื่อเข้าใช้แล้ว

7. ยินดีด้วย

คุณดำเนินการ Codelab เสร็จแล้ว - Android FIDO2 API แรกของคุณ

สิ่งที่คุณได้เรียนรู้

  • วิธีลงทะเบียนข้อมูลเข้าสู่ระบบโดยใช้ผู้ใช้ที่ยืนยัน Authenticator ของแพลตฟอร์ม
  • วิธีตรวจสอบสิทธิ์ผู้ใช้โดยใช้ Authenticator ที่ลงทะเบียน
  • ตัวเลือกที่พร้อมใช้งานสำหรับการลงทะเบียน Authenticator ใหม่
  • แนวทางปฏิบัติแนะนำเกี่ยวกับ UX สำหรับการตรวจสอบสิทธิ์อีกครั้งโดยใช้เซ็นเซอร์ข้อมูลไบโอเมตริก

ขั้นตอนถัดไป

  • ดูวิธีสร้างประสบการณ์ที่คล้ายกันในเว็บไซต์

คุณดูข้อมูลนี้ได้โดยลองใช้ Codelab ของ WebAuthn แรกของคุณ

แหล่งข้อมูล

ขอขอบคุณ Yuriy Ackermann จาก FIDO Alliance ที่ให้ความช่วยเหลือคุณ