1. ก่อนเริ่มต้น
โซลูชันการตรวจสอบสิทธิ์แบบดั้งเดิมก่อให้เกิดปัญหาด้านความปลอดภัยและความสามารถในการใช้งานหลายประการ
รหัสผ่านเป็นที่นิยมใช้กันมาก แต่...
- ลืมได้ง่าย
 - ผู้ใช้ต้องมีความรู้ในการสร้างรหัสผ่านที่รัดกุม
 - ง่ายต่อการฟิชชิง รวบรวม และเล่นซ้ำโดยผู้โจมตี
 
Android พยายามสร้าง Credential Manager API เพื่อลดความซับซ้อนของประสบการณ์การลงชื่อเข้าใช้และจัดการความเสี่ยงด้านความปลอดภัยด้วยการรองรับพาสคีย์ ซึ่งเป็นมาตรฐานอุตสาหกรรมรุ่นถัดไปสำหรับการตรวจสอบสิทธิ์แบบไม่ต้องใช้รหัสผ่าน
Credential Manager รวมการรองรับพาสคีย์เข้ากับวิธีการตรวจสอบสิทธิ์แบบดั้งเดิม เช่น รหัสผ่าน การลงชื่อเข้าใช้ด้วย Google เป็นต้น
ผู้ใช้จะสร้างพาสคีย์และจัดเก็บไว้ในเครื่องมือจัดการรหัสผ่านบน Google ได้ ซึ่งจะซิงค์พาสคีย์เหล่านั้นในอุปกรณ์ Android ที่ผู้ใช้ลงชื่อเข้าใช้ คุณต้องสร้างพาสคีย์ เชื่อมโยงกับบัญชีผู้ใช้ และจัดเก็บคีย์สาธารณะไว้ในเซิร์ฟเวอร์ก่อน ผู้ใช้จึงจะลงชื่อเข้าใช้ด้วยพาสคีย์ได้
ในโค้ดแล็บนี้ คุณจะได้เรียนรู้วิธีลงชื่อสมัครใช้โดยใช้พาสคีย์และรหัสผ่านด้วย Credential Manager API และใช้เพื่อวัตถุประสงค์ในการตรวจสอบสิทธิ์ในอนาคต ขั้นตอนการส่งออกมี 2 ขั้นตอน ได้แก่
- ลงชื่อสมัครใช้ : ใช้พาสคีย์และรหัสผ่าน
 - ลงชื่อเข้าใช้ : ใช้พาสคีย์และรหัสผ่านที่บันทึกไว้
 
ข้อกำหนดเบื้องต้น
- ทำความเข้าใจพื้นฐานเกี่ยวกับวิธีเรียกใช้แอปใน Android Studio
 - ทำความเข้าใจพื้นฐานเกี่ยวกับขั้นตอนการตรวจสอบสิทธิ์ในแอป Android
 - ทำความเข้าใจพื้นฐานเกี่ยวกับพาสคีย์
 
สิ่งที่คุณจะได้เรียนรู้
- วิธีสร้างพาสคีย์
 - วิธีบันทึกรหัสผ่านในเครื่องมือจัดการรหัสผ่าน
 - วิธีตรวจสอบสิทธิ์ผู้ใช้ด้วยพาสคีย์หรือรหัสผ่านที่บันทึกไว้
 
สิ่งที่คุณต้องมี
อุปกรณ์ต่อไปนี้ต้องทำงานร่วมกัน
- อุปกรณ์ Android ที่ใช้ Android 9 ขึ้นไป (สำหรับพาสคีย์) และ Android 4.4 ขึ้นไป(สำหรับการรับรองความถูกต้องด้วยรหัสผ่านผ่าน Credential Manager API)
 - อุปกรณ์ที่ควรมีเซ็นเซอร์ไบโอเมตริก
 - อย่าลืมลงทะเบียนข้อมูลไบโอเมตริก (หรือล็อกหน้าจอ)
 - เวอร์ชันปลั๊กอิน Kotlin : 1.8.10
 
2. ตั้งค่า
- โคลนที่เก็บนี้ในแล็ปท็อปจากสาขา credman_codelab : https://github.com/android/identity-samples/tree/credman_codelab
 
git clone -b credman_codelab https://github.com/android/identity-samples.git
- ไปที่โมดูล CredentialManager และเปิดโปรเจ็กต์ใน Android Studio
 
มาดูสถานะเริ่มต้นของแอปกัน
หากต้องการดูวิธีการทำงานของสถานะเริ่มต้นของแอป ให้ทำตามขั้นตอนต่อไปนี้
- เปิดแอป
 - คุณจะเห็นหน้าจอหลักที่มีปุ่มลงชื่อสมัครใช้และลงชื่อเข้าใช้ ปุ่มเหล่านี้ยังไม่ทํางาน แต่เราจะเปิดใช้ฟังก์ชันการทํางานของปุ่มในส่วนถัดไป
 

3. เพิ่มความสามารถในการลงชื่อสมัครใช้โดยใช้พาสคีย์
เมื่อลงชื่อสมัครใช้บัญชีใหม่ในแอป Android ที่ใช้ Credential Manager API ผู้ใช้จะสร้างพาสคีย์สำหรับบัญชีได้ ระบบจะจัดเก็บพาสคีย์นี้อย่างปลอดภัยในผู้ให้บริการข้อมูลเข้าสู่ระบบที่ผู้ใช้เลือกไว้ และใช้สำหรับการลงชื่อเข้าใช้ในอนาคตโดยไม่ต้องให้ผู้ใช้ป้อนรหัสผ่านทุกครั้ง
ตอนนี้คุณจะต้องสร้างพาสคีย์และลงทะเบียนข้อมูลเข้าสู่ระบบของผู้ใช้โดยใช้ข้อมูลไบโอเมตริก/การล็อกหน้าจอ
ลงชื่อสมัครใช้ด้วยพาสคีย์
โค้ดภายใน Credential Manager/app/main/java/SignUpFragment.kt จะกำหนดช่องข้อความ "username" และปุ่มลงชื่อสมัครใช้ด้วยพาสคีย์

ส่งภารกิจและการตอบกลับ JSON อื่นๆ ไปยังการเรียก createPasskey()
ก่อนสร้างพาสคีย์ คุณต้องขอข้อมูลจากเซิร์ฟเวอร์เพื่อส่งไปยัง Credential Manager API ระหว่างการเรียกใช้ createCredential()
คุณมีคำตอบจำลองอยู่ในชิ้นงานของโปรเจ็กต์แล้ว ซึ่งเรียกว่า RegFromServer.txt ซึ่งจะแสดงผลพารามิเตอร์ที่จำเป็นในโค้ดแล็บนี้
- ในแอป ให้ไปที่ SignUpFragment.kt แล้วค้นหาเมธอด signUpWithPasskeys ซึ่งคุณจะเขียนตรรกะในการสร้างพาสคีย์และอนุญาตให้ผู้ใช้เข้าสู่ระบบ คุณจะเห็นเมธอดนี้ในคลาสเดียวกัน
 - ตรวจสอบบล็อก else ที่มีความคิดเห็นเพื่อเรียก 
createPasskey()แล้วแทนที่ด้วยโค้ดต่อไปนี้ 
SignUpFragment.kt
//TODO : Call createPasskey() to signup with passkey
val data = createPasskey()
ระบบจะเรียกใช้เมธอดนี้เมื่อคุณกรอกชื่อผู้ใช้ที่ถูกต้องบนหน้าจอ
- ในเมธอด 
createPasskey()คุณต้องสร้างCreatePublicKeyCredentialRequest()ที่มีพารามิเตอร์ที่จำเป็นซึ่งแสดงผล 
SignUpFragment.kt
//TODO create a CreatePublicKeyCredentialRequest() with necessary registration json from server
val request = CreatePublicKeyCredentialRequest(fetchRegistrationJsonFromServer())
เมธอด fetchRegistrationJsonFromServer() จะอ่านการตอบกลับ JSON PublicKeyCredentialCreationOptions ของเซิร์ฟเวอร์จำลองจากชิ้นงานและแสดงผล JSON การลงทะเบียนที่จะส่งไปขณะสร้างพาสคีย์
- ค้นหาเมธอด 
fetchRegistrationJsonFromServer()แล้วแทนที่ TODO ด้วยโค้ดต่อไปนี้เพื่อแสดงผล JSON และนําคำสั่งแสดงผลสตริงว่างออก 
SignUpFragment.kt
//TODO fetch registration mock response
val response = requireContext().readFromAsset("RegFromServer")
//Update userId,challenge, name and Display name in the mock
return response.replace("<userId>", getEncodedUserId())
   .replace("<userName>", binding.username.text.toString())
   .replace("<userDisplayName>", binding.username.text.toString())
   .replace("<challenge>", getEncodedChallenge())
- JSON นี้ไม่สมบูรณ์และมี 4 ช่องที่ต้องแทนที่
 - UserId ต้องไม่ซ้ำกันเพื่อให้ผู้ใช้สร้างพาสคีย์ได้หลายรายการ (หากจำเป็น) แทนที่ 
<userId>ด้วยค่าuserIdที่สร้างขึ้น <challenge>จะต้องไม่ซ้ำกันด้วย คุณจึงจะสร้างภารกิจแบบสุ่มที่ไม่ซ้ำกันได้ วิธีการอยู่ในโค้ดของคุณอยู่แล้ว
การตอบกลับ PublicKeyCredentialCreationOptions ของเซิร์ฟเวอร์จริงอาจแสดงตัวเลือกเพิ่มเติม ตัวอย่างของช่องเหล่านี้มีดังนี้
{
  "challenge": String,
  "rp": {
    "name": String,
    "id": String
  },
  "user": {
    "id": String,
    "name": String,
    "displayName": String
  },
  "pubKeyCredParams": [
    {
      "type": "public-key",
      "alg": -7
    },
    {
      "type": "public-key",
      "alg": -257
    }
  ],
  "timeout": 1800000,
  "attestation": "none",
  "excludeCredentials": [],
  "authenticatorSelection": {
    "authenticatorAttachment": "platform",
    "requireResidentKey": true,
    "residentKey": "required",
    "userVerification": "required"
  }
}
ตารางต่อไปนี้อธิบายพารามิเตอร์ที่สําคัญบางรายการในออบเจ็กต์ PublicKeyCredentialCreationOptions
พารามิเตอร์  | คำอธิบาย  | 
สตริงแบบสุ่มที่เซิร์ฟเวอร์สร้างขึ้นซึ่งมีข้อมูลดิบเพียงพอที่จะทำให้คาดเดาได้ยาก โดยควรมีความยาวอย่างน้อย 16 ไบต์ ข้อมูลนี้ต้องระบุ แต่จะไม่ได้ใช้ในระหว่างการลงทะเบียน เว้นแต่จะทำการรับรอง  | |
รหัสที่ไม่ซ้ำกันของผู้ใช้ ค่านี้ต้องไม่มีข้อมูลที่ระบุตัวบุคคลได้ เช่น อีเมลหรือชื่อผู้ใช้ ค่าแบบสุ่ม 16 ไบต์ที่สร้างขึ้นต่อบัญชีจะทํางานได้ดี  | |
ช่องนี้ควรมีตัวระบุที่ไม่ซ้ำกันสำหรับบัญชีที่ผู้ใช้จะจดจำได้ เช่น อีเมลหรือชื่อผู้ใช้ ซึ่งจะแสดงในตัวเลือกบัญชี (หากใช้ชื่อผู้ใช้ ให้ใช้ค่าเดียวกับในการตรวจสอบสิทธิ์ด้วยรหัสผ่าน)  | |
ช่องนี้เป็นชื่อบัญชีที่เรียกง่ายขึ้นซึ่งไม่บังคับ  | |
บุคคลที่เชื่อถือจะสอดคล้องกับรายละเอียดแอปพลิเคชันของคุณ โดยมีแอตทริบิวต์ต่อไปนี้ 
  | |
รายการอัลกอริทึมและประเภทคีย์ที่อนุญาต รายการนี้ต้องมีองค์ประกอบอย่างน้อย 1 รายการ  | |
ผู้ใช้ที่พยายามลงทะเบียนอุปกรณ์อาจลงทะเบียนอุปกรณ์เครื่องอื่นแล้ว หากต้องการจำกัดการสร้างข้อมูลเข้าสู่ระบบหลายรายการสำหรับบัญชีเดียวกันในโปรแกรมตรวจสอบสิทธิ์รายการเดียว คุณก็สามารถละเว้นอุปกรณ์เหล่านี้ได้ สมาชิก   | |
ระบุว่าควรแนบอุปกรณ์ในแพลตฟอร์มหรือไม่ หรือไม่จำเป็นต้องแนบอุปกรณ์ ตั้งค่านี้เป็น   | |
  | ระบุค่า   | 
สร้างข้อมูลเข้าสู่ระบบ
- เมื่อสร้าง 
CreatePublicKeyCredentialRequest()แล้ว คุณต้องเรียกใช้การเรียกcreateCredential()ด้วยคําขอที่สร้างไว้ 
SignUpFragment.kt
//TODO call createCredential() with createPublicKeyCredentialRequest
try {
   response = credentialManager.createCredential(
       requireActivity(),
       request
   ) as CreatePublicKeyCredentialResponse
} catch (e: CreateCredentialException) {
   configureProgress(View.INVISIBLE)
   handlePasskeyFailure(e)
}
- คุณส่งข้อมูลที่จําเป็นไปยัง 
createCredential() - เมื่อส่งคำขอสำเร็จแล้ว คุณจะเห็นหน้าจอด้านล่างแจ้งให้สร้างพาสคีย์
 - ตอนนี้ผู้ใช้สามารถยืนยันตัวตนผ่านข้อมูลไบโอเมตริกหรือการล็อกหน้าจอ ฯลฯ
 - คุณจัดการการแสดงผลที่แสดงผลแล้วและจัดการข้อยกเว้นหากคําขอไม่สําเร็จหรือประสบปัญหาเนื่องจากเหตุผลบางอย่าง ข้อความแสดงข้อผิดพลาดจะบันทึกไว้ที่นี่และแสดงในแอปในกล่องโต้ตอบข้อผิดพลาด คุณสามารถตรวจสอบบันทึกข้อผิดพลาดฉบับเต็มผ่าน Android Studio หรือคำสั่ง 
adb debug 

- สุดท้าย คุณต้องดำเนินการตามขั้นตอนการลงทะเบียนให้เสร็จสมบูรณ์ แอปจะส่งข้อมูลเข้าสู่ระบบคีย์สาธารณะไปยังเซิร์ฟเวอร์ซึ่งจะลงทะเบียนคีย์กับผู้ใช้ปัจจุบัน
 
ในส่วนนี้ เราใช้เซิร์ฟเวอร์จำลอง ดังนั้นเราจึงแสดงผลเป็น "จริง" เพื่อระบุว่าเซิร์ฟเวอร์ได้บันทึกคีย์สาธารณะที่ลงทะเบียนไว้เพื่อใช้ตรวจสอบสิทธิ์และตรวจสอบความถูกต้องในอนาคต อ่านข้อมูลเพิ่มเติมเกี่ยวกับการลงทะเบียนพาสคีย์ฝั่งเซิร์ฟเวอร์เพื่อนำไปใช้งานเอง
ในเมธอด signUpWithPasskeys() ให้ค้นหาความคิดเห็นที่เกี่ยวข้อง แล้วแทนที่ด้วยโค้ดต่อไปนี้
SignUpFragment.kt
//TODO : complete the registration process after sending public key credential to your server and let the user in
data?.let {
   registerResponse()
   DataProvider.setSignedInThroughPasskeys(true)
   listener.showHome()
}
registerResponse()จะแสดงผลเป็นtrueซึ่งระบุว่าเซิร์ฟเวอร์จำลองได้บันทึกคีย์สาธารณะไว้ใช้ในอนาคต- ตั้งค่าสถานะ 
setSignedInThroughPasskeysเป็นtrue - เมื่อเข้าสู่ระบบแล้ว ให้เปลี่ยนเส้นทางผู้ใช้ไปยังหน้าจอหลัก
 
PublicKeyCredential จริงอาจมีฟิลด์มากกว่านี้ ตัวอย่างของช่องเหล่านี้แสดงอยู่ด้านล่าง
{
  "id": String,
  "rawId": String,
  "type": "public-key",
  "response": {
    "clientDataJSON": String,
    "attestationObject": String,
  }
}
ตารางต่อไปนี้อธิบายพารามิเตอร์ที่สําคัญบางรายการในออบเจ็กต์ PublicKeyCredential
พารามิเตอร์  | คำอธิบาย  | 
รหัสที่เข้ารหัส Base64URL ของพาสคีย์ที่สร้างขึ้น รหัสนี้ช่วยให้เบราว์เซอร์ทราบว่ามีพาสคีย์ที่ตรงกันในอุปกรณ์หรือไม่เมื่อตรวจสอบสิทธิ์ ค่านี้ต้องจัดเก็บไว้ในฐานข้อมูลบนแบ็กเอนด์  | |
รหัสข้อมูลเข้าสู่ระบบเวอร์ชันออบเจ็กต์   | |
ออบเจ็กต์   | |
ออบเจ็กต์การรับรองที่เข้ารหัส   | 
เรียกใช้แอป แล้วคุณจะคลิกปุ่มลงชื่อสมัครใช้ด้วยพาสคีย์และสร้างพาสคีย์ได้
4. บันทึกรหัสผ่านในผู้ให้บริการข้อมูลเข้าสู่ระบบ
ในแอปนี้ ภายในหน้าจอลงชื่อสมัครใช้ คุณได้ลงชื่อสมัครใช้ด้วยชื่อผู้ใช้และรหัสผ่านไว้แล้วเพื่อวัตถุประสงค์ในการสาธิต
หากต้องการบันทึกข้อมูลเข้าสู่ระบบรหัสผ่านของผู้ใช้กับผู้ให้บริการรหัสผ่าน คุณจะใช้ CreatePasswordRequest เพื่อส่งไปยัง createCredential() เพื่อบันทึกรหัสผ่าน
- ค้นหาเมธอด 
signUpWithPassword()แล้วแทนที่ TODO ด้วยการเรียกใช้createPasswordดังนี้ 
SignUpFragment.kt
//TODO : Save the user credential password with their password provider
createPassword()
- ในเมธอด 
createPassword()คุณต้องสร้างคำขอรหัสผ่านเช่นนี้ โดยแทนที่ TODO ด้วยโค้ดต่อไปนี้ 
SignUpFragment.kt
//TODO : CreatePasswordRequest with entered username and password
val request = CreatePasswordRequest(
   binding.username.text.toString(),
   binding.password.text.toString()
)
- ถัดไป ภายในเมธอด 
createPassword()ให้สร้างข้อมูลเข้าสู่ระบบที่มีคำขอสร้างรหัสผ่าน และบันทึกข้อมูลเข้าสู่ระบบรหัสผ่านของผู้ใช้ด้วยผู้ให้บริการรหัสผ่าน แทนที่ TODO ด้วยโค้ดต่อไปนี้ 
SignUpFragment.kt
//TODO : Create credential with created password request
try {
   credentialManager.createCredential(requireActivity(), request) as CreatePasswordResponse
} catch (e: Exception) {
   Log.e("Auth", " Exception Message : " + e.message)
}
- ตอนนี้คุณได้บันทึกข้อมูลเข้าสู่ระบบด้วยรหัสผ่านไว้กับผู้ให้บริการรหัสผ่านของผู้ใช้เพื่อตรวจสอบสิทธิ์ด้วยรหัสผ่านด้วยการแตะเพียงครั้งเดียวเรียบร้อยแล้ว
 
5. เพิ่มความสามารถในการตรวจสอบสิทธิ์ด้วยพาสคีย์หรือรหัสผ่าน
ตอนนี้คุณก็พร้อมที่จะใช้พาสคีย์เพื่อตรวจสอบสิทธิ์เข้าสู่แอปอย่างปลอดภัยแล้ว

รับภารกิจและตัวเลือกอื่นๆ เพื่อส่งไปยังการเรียก getPasskey()
คุณต้องขอพารามิเตอร์เพื่อส่งใน WebAuthn JSON จากเซิร์ฟเวอร์ รวมถึงคำขอแจ้งให้ดำเนินการ (Challenge) ก่อนขอให้ผู้ใช้ตรวจสอบสิทธิ์
คุณมีคำตอบจำลองอยู่ในชิ้นงาน (AuthFromServer.txt) ซึ่งแสดงผลพารามิเตอร์ดังกล่าวในโค้ดแล็บนี้อยู่แล้ว
- ในแอป ให้ไปที่ SignInFragment.kt แล้วค้นหาเมธอด 
signInWithSavedCredentialsที่คุณจะใช้เขียนตรรกะสำหรับการตรวจสอบสิทธิ์ผ่านพาสคีย์หรือรหัสผ่านที่บันทึกไว้และอนุญาตให้ผู้ใช้เข้าสู่ระบบ - ตรวจสอบบล็อก else ที่มีความคิดเห็นเพื่อเรียก 
createPasskey()แล้วแทนที่ด้วยโค้ดต่อไปนี้ 
SignInFragment.kt
//TODO : Call getSavedCredentials() method to signin using passkey/password
val data = getSavedCredentials()
- ในเมธอด getSavedCredentials() คุณต้องสร้าง 
GetPublicKeyCredentialOption()ที่มีพารามิเตอร์ที่จำเป็นในการรับข้อมูลเข้าสู่ระบบจากผู้ให้บริการข้อมูลเข้าสู่ระบบ 
SigninFragment.kt
//TODO create a GetPublicKeyCredentialOption() with necessary registration json from server
val getPublicKeyCredentialOption =
   GetPublicKeyCredentialOption(fetchAuthJsonFromServer(), null)
เมธอด fetchAuthJsonFromServer() จะอ่านการตอบกลับ JSON การตรวจสอบสิทธิ์จากชิ้นงานและแสดงผล JSON การตรวจสอบสิทธิ์เพื่อดึงข้อมูลพาสคีย์ทั้งหมดที่เชื่อมโยงกับบัญชีผู้ใช้นี้
พารามิเตอร์ที่ 2 ของ GetPublicKeyCredentialOption() คือ clientDataHash ซึ่งเป็นแฮชที่ใช้เพื่อยืนยันตัวตนของฝ่ายที่เชื่อถือ ตั้งค่านี้เฉพาะในกรณีที่คุณตั้งค่า GetCredentialRequest.origin สําหรับแอปตัวอย่าง จะมีการกําหนดค่านี้เป็น null
- ค้นหาเมธอด fetchAuthJsonFromServer() แล้วแทนที่ TODO ด้วยโค้ดต่อไปนี้เพื่อแสดงผล JSON และนําออกคำสั่งแสดงผลสตริงว่าง
 
SignInFragment.kt
//TODO fetch authentication mock json
return requireContext().readFromAsset("AuthFromServer")
หมายเหตุ : เซิร์ฟเวอร์ของโค้ดแล็บนี้ออกแบบมาเพื่อแสดงผล JSON ที่คล้ายกับพจนานุกรม PublicKeyCredentialRequestOptions ที่ส่งไปยังการเรียก getCredential() ของ API มากที่สุด ข้อมูลโค้ดต่อไปนี้มีตัวอย่างตัวเลือก 2-3 รายการที่คุณอาจได้รับในการตอบกลับจริง
{
  "challenge": String,
  "rpId": String,
  "userVerification": "",
  "timeout": 1800000
}
ตารางต่อไปนี้อธิบายพารามิเตอร์ที่สําคัญบางรายการในออบเจ็กต์ PublicKeyCredentialRequestOptions
พารามิเตอร์  | คำอธิบาย  | 
ภารกิจที่เซิร์ฟเวอร์สร้างขึ้นในออบเจ็กต์   | |
รหัส RP คือโดเมน เว็บไซต์จะระบุโดเมนหรือนามสกุลที่จดทะเบียนได้ก็ได้ ค่านี้ต้องตรงกับพารามิเตอร์   | 
- ถัดไปคุณต้องสร้างออบเจ็กต์ 
PasswordOption()เพื่อดึงข้อมูลรหัสผ่านที่บันทึกไว้ทั้งหมดในผู้ให้บริการรหัสผ่านผ่าน Credential Manager API สำหรับบัญชีผู้ใช้นี้ ในเมธอดgetSavedCredentials()ให้ค้นหา TODO แล้วแทนที่ด้วยข้อความต่อไปนี้ 
SigninFragment.kt
//TODO create a PasswordOption to retrieve all the associated user's password
val getPasswordOption = GetPasswordOption()
รับข้อมูลเข้าสู่ระบบ
- ถัดไป คุณต้องเรียกใช้คําขอ 
getCredential()พร้อมตัวเลือกทั้งหมดข้างต้นเพื่อดึงข้อมูลเข้าสู่ระบบที่เชื่อมโยง 
SignInFragment.kt
//TODO call getCredential() with required credential options
val result = try {
   credentialManager.getCredential(
       requireActivity(),
       GetCredentialRequest(
           listOf(
               getPublicKeyCredentialOption,
               getPasswordOption
           )
     )
   )
} catch (e: Exception) {
   configureViews(View.INVISIBLE, true)
   Log.e("Auth", "getCredential failed with exception: " + e.message.toString())
   activity?.showErrorAlert(
       "An error occurred while authenticating through saved credentials. Check logs for additional details"
   )
   return null
}
if (result.credential is PublicKeyCredential) {
   val cred = result.credential as PublicKeyCredential
   DataProvider.setSignedInThroughPasskeys(true)
   return "Passkey: ${cred.authenticationResponseJson}"
}
if (result.credential is PasswordCredential) {
   val cred = result.credential as PasswordCredential
   DataProvider.setSignedInThroughPasskeys(false)
   return "Got Password - User:${cred.id} Password: ${cred.password}"
}
if (result.credential is CustomCredential) {
   //If you are also using any external sign-in libraries, parse them here with the utility functions provided.
}
- คุณส่งข้อมูลที่จําเป็นไปยัง 
getCredential()ซึ่งจะนํารายการตัวเลือกข้อมูลเข้าสู่ระบบและบริบทกิจกรรมมาแสดงผลตัวเลือกใน Bottom Sheet ในบริบทนั้น - เมื่อส่งคำขอสำเร็จแล้ว คุณจะเห็นหน้าจอด้านล่างแสดงข้อมูลเข้าสู่ระบบทั้งหมดที่สร้างไว้สำหรับบัญชีที่เชื่อมโยง
 - ตอนนี้ผู้ใช้สามารถยืนยันตัวตนผ่านข้อมูลไบโอเมตริกหรือการล็อกหน้าจอ ฯลฯ เพื่อตรวจสอบสิทธิ์ข้อมูลเข้าสู่ระบบที่เลือก
 - หากข้อมูลเข้าสู่ระบบที่เลือกคือ 
PublicKeyCredentialให้ตั้งค่า FlagsetSignedInThroughPasskeysเป็นtrueมิเช่นนั้น ให้ตั้งค่าเป็นfalse 
ข้อมูลโค้ดต่อไปนี้มีตัวอย่างออบเจ็กต์ PublicKeyCredential
{
  "id": String
  "rawId": String
  "type": "public-key",
  "response": {
    "clientDataJSON": String
    "authenticatorData": String
    "signature": String
    "userHandle": String
  }
}
ตารางต่อไปนี้ไม่ได้ครอบคลุมทั้งหมด แต่มีพารามิเตอร์ที่สําคัญในแออบเจ็กต์ PublicKeyCredential
พารามิเตอร์  | คำอธิบาย  | 
รหัสที่เข้ารหัส Base64URL ของข้อมูลเข้าสู่ระบบพาสคีย์ที่ตรวจสอบสิทธิ์แล้ว  | |
รหัสข้อมูลเข้าสู่ระบบเวอร์ชันออบเจ็กต์   | |
ออบเจ็กต์   | |
ออบเจ็กต์   | |
ออบเจ็กต์   | |
ออบเจ็กต์   | 
- สุดท้าย คุณต้องทำตามกระบวนการตรวจสอบสิทธิ์ให้เสร็จสมบูรณ์ โดยปกติแล้ว หลังจากผู้ใช้ตรวจสอบสิทธิ์พาสคีย์เสร็จแล้ว แอปจะส่งข้อมูลเข้าสู่ระบบคีย์สาธารณะที่มีการยืนยันการตรวจสอบสิทธิ์ไปยังเซิร์ฟเวอร์ ซึ่งจะยืนยันการยืนยันและตรวจสอบสิทธิ์ของผู้ใช้
 
ในที่นี้ เราใช้เซิร์ฟเวอร์จำลอง ดังนั้นเราจึงแสดงผล true เพื่อระบุว่าเซิร์ฟเวอร์ได้ยืนยันการกล่าวอ้างแล้ว คุณสามารถอ่านข้อมูลเพิ่มเติมเกี่ยวกับการตรวจสอบสิทธิ์พาสคีย์ฝั่งเซิร์ฟเวอร์เพื่อนำไปใช้งานเอง
ภายในเมธอด signInWithSavedCredentials() ให้ค้นหาความคิดเห็นที่เกี่ยวข้อง แล้วแทนที่ด้วยโค้ดต่อไปนี้
SignInFragment.kt
//TODO : complete the authentication process after validating the public key credential to your server and let the user in.
data?.let {
   sendSignInResponseToServer()
   listener.showHome()
}
sendSigninResponseToServer()จะแสดงผลเป็น "จริง" ซึ่งบ่งบอกว่าเซิร์ฟเวอร์ (จำลอง) ได้ตรวจสอบคีย์สาธารณะเพื่อใช้ในอนาคตแล้ว- เมื่อเข้าสู่ระบบแล้ว ให้เปลี่ยนเส้นทางผู้ใช้ไปยังหน้าจอหลัก
 
เปิดแอปแล้วไปที่ลงชื่อเข้าใช้ > ลงชื่อเข้าใช้ด้วยพาสคีย์/รหัสผ่านที่บันทึกไว้ แล้วลองลงชื่อเข้าใช้โดยใช้ข้อมูลเข้าสู่ระบบที่บันทึกไว้
ลองใช้
คุณใช้การสร้างพาสคีย์ การบันทึกรหัสผ่านในเครื่องมือจัดการข้อมูลเข้าสู่ระบบ และการรับรองผ่านพาสคีย์หรือรหัสผ่านที่บันทึกไว้โดยใช้ Credential Manager API ในแอป Android
6. ยินดีด้วย
คุณทำ Codelab นี้เสร็จแล้ว หากต้องการตรวจสอบโซลูชันขั้นสุดท้าย โปรดไปที่ https://github.com/android/identity-samples/tree/main/CredentialManager
หากมีคำถาม โปรดถามใน StackOverflow โดยใช้แท็ก passkey