สร้างประสบการณ์การลงชื่อเข้าใช้ที่ใช้ประโยชน์จากพาสคีย์โดยที่ยังช่วยให้ผู้ใช้ใช้รหัสผ่านเดิมได้
พาสคีย์มาแทนที่รหัสผ่าน และทำให้บัญชีผู้ใช้บนเว็บปลอดภัย ง่ายขึ้น และใช้งานง่ายยิ่งขึ้น แต่การเปลี่ยนจากการตรวจสอบสิทธิ์ด้วยรหัสผ่านเป็นพาสคีย์อาจทำให้ประสบการณ์ของผู้ใช้มีความซับซ้อนยิ่งขึ้น การใช้การป้อนแบบฟอร์มอัตโนมัติเพื่อแนะนำพาสคีย์จะช่วยสร้างประสบการณ์การใช้งานแบบรวม
เหตุใดจึงควรใช้การป้อนแบบฟอร์มอัตโนมัติเพื่อลงชื่อเข้าใช้ด้วยพาสคีย์
พาสคีย์ช่วยให้ผู้ใช้ลงชื่อเข้าใช้เว็บไซต์ได้เพียงแค่ใช้ลายนิ้วมือ ใบหน้า หรือ PIN ของอุปกรณ์
ตามหลักการแล้ว ไม่ควรให้ผู้ใช้ใช้รหัสผ่าน และขั้นตอนการตรวจสอบสิทธิ์อาจทำได้ง่ายๆ ด้วยการกดปุ่มลงชื่อเข้าใช้เพียงครั้งเดียว เมื่อผู้ใช้แตะปุ่ม กล่องโต้ตอบตัวเลือกบัญชีจะปรากฏขึ้น ผู้ใช้สามารถเลือกบัญชี ปลดล็อกหน้าจอเพื่อยืนยัน และลงชื่อเข้าใช้ได้
แต่การเปลี่ยนจากรหัสผ่านเป็นการตรวจสอบสิทธิ์ด้วยพาสคีย์อาจทำได้ยาก เมื่อผู้ใช้เปลี่ยนไปใช้พาสคีย์ ผู้ที่ใช้รหัสผ่านและเว็บไซต์จะต้องรองรับผู้ใช้ทั้ง 2 ประเภท ผู้ใช้ไม่ควรต้องจดจำว่าได้เปลี่ยนมาใช้พาสคีย์ในเว็บไซต์ใด ดังนั้นการขอให้ผู้ใช้เลือกวิธีที่จะใช้ตั้งแต่แรกอาจเป็น UX ที่แย่
พาสคีย์ก็เป็นเทคโนโลยีใหม่เช่นกัน การอธิบายและตรวจสอบว่าผู้ใช้จะรู้สึกสบายใจ ในการใช้งานอาจเป็นเรื่องท้าทายสำหรับเว็บไซต์ เราสามารถอาศัยประสบการณ์ของผู้ใช้ที่คุ้นเคยในการป้อนรหัสผ่านอัตโนมัติเพื่อแก้ปัญหาทั้ง 2 อย่าง
UI แบบมีเงื่อนไข
หากต้องการสร้างประสบการณ์ของผู้ใช้ที่มีประสิทธิภาพสำหรับทั้งผู้ใช้พาสคีย์และรหัสผ่าน คุณสามารถใส่พาสคีย์ไว้ในคำแนะนำของการป้อนข้อความอัตโนมัติ ซึ่งเรียกว่า UI แบบมีเงื่อนไข และเป็นส่วนหนึ่งของมาตรฐาน WebAuthn
ทันทีที่ผู้ใช้แตะช่องป้อนชื่อผู้ใช้ กล่องโต้ตอบคำแนะนำการป้อนข้อความอัตโนมัติจะปรากฏขึ้น ซึ่งไฮไลต์พาสคีย์ที่เก็บไว้พร้อมกับคำแนะนำการป้อนรหัสผ่านอัตโนมัติ จากนั้นผู้ใช้สามารถเลือกบัญชีและใช้การล็อกหน้าจอของอุปกรณ์เพื่อลงชื่อเข้าใช้ได้
ด้วยวิธีนี้ผู้ใช้จะลงชื่อเข้าใช้เว็บไซต์ด้วยแบบฟอร์มที่มีอยู่ราวกับว่าไม่มีอะไรเปลี่ยนแปลง แต่เพิ่มประโยชน์ด้านความปลอดภัยของพาสคีย์หากมี
วิธีการทำงาน
หากต้องการตรวจสอบสิทธิ์ด้วยพาสคีย์ ให้ใช้ WebAuthn API
องค์ประกอบ 4 อย่างในขั้นตอนการตรวจสอบสิทธิ์ด้วยพาสคีย์ ได้แก่ ผู้ใช้
- แบ็กเอนด์: เซิร์ฟเวอร์แบ็กเอนด์ที่เก็บฐานข้อมูลบัญชีซึ่งจัดเก็บคีย์สาธารณะและข้อมูลเมตาอื่นๆ เกี่ยวกับพาสคีย์
- ฟรอนท์เอนด์: ฟรอนท์เอนด์ที่สื่อสารกับเบราว์เซอร์และส่งคำขอดึงข้อมูลไปยังแบ็กเอนด์
- เบราว์เซอร์: เบราว์เซอร์ของผู้ใช้ที่เรียกใช้ JavaScript
- Authenticator: Authenticator ของผู้ใช้ที่สร้างและจัดเก็บพาสคีย์ ซึ่งอาจอยู่บนอุปกรณ์เดียวกับเบราว์เซอร์ (เช่น เมื่อใช้ Windows Hello) หรืออุปกรณ์อื่น เช่น โทรศัพท์
- ทันทีที่ผู้ใช้เข้าสู่ฟรอนท์เอนด์ ผู้ใช้ก็จะขอการยืนยันตัวตนจากแบ็กเอนด์เพื่อตรวจสอบสิทธิ์ด้วยพาสคีย์และการเรียกใช้
navigator.credentials.get()
เพื่อเริ่มการตรวจสอบสิทธิ์ด้วยพาสคีย์ ซึ่งแสดงผลPromise
- เมื่อผู้ใช้วางเคอร์เซอร์ในช่องลงชื่อเข้าใช้ เบราว์เซอร์จะแสดงกล่องโต้ตอบ การป้อนข้อความอัตโนมัติ ซึ่งรวมถึงพาสคีย์ กล่องโต้ตอบการตรวจสอบสิทธิ์จะปรากฏขึ้น หากผู้ใช้เลือกพาสคีย์
- หลังจากที่ผู้ใช้ยืนยันตัวตนโดยใช้การล็อกหน้าจอของอุปกรณ์ สัญญาดังกล่าวจะได้รับการแก้ไขและมีการส่งข้อมูลเข้าสู่ระบบคีย์สาธารณะไปยังฟรอนท์เอนด์
- ฟรอนท์เอนด์จะส่งข้อมูลเข้าสู่ระบบคีย์สาธารณะไปยังแบ็กเอนด์ แบ็กเอนด์จะยืนยันลายเซ็นกับคีย์สาธารณะของบัญชีที่ตรงกันในฐานข้อมูล หากสำเร็จ ผู้ใช้จะลงชื่อเข้าใช้
ข้อกำหนดเบื้องต้น
Safari บน iOS 16, iPadOS 16 และ macOS Ventura รองรับ UI ของ WebAuthn ตามเงื่อนไขแบบสาธารณะ นอกจากนี้ยังพร้อมใช้งานบน Chrome บน Android, macOS และ Windows 11 22H2 ด้วย
ตรวจสอบสิทธิ์ด้วยพาสคีย์ผ่านการป้อนแบบฟอร์มอัตโนมัติ
เมื่อผู้ใช้ต้องการลงชื่อเข้าใช้ คุณสามารถเรียก WebAuthn get
แบบมีเงื่อนไขได้
เพื่อระบุว่าอาจมีพาสคีย์รวมอยู่ในคำแนะนำการป้อนข้อความอัตโนมัติ การเรียกแบบมีเงื่อนไขไปยัง API navigator.credentials.get()
ของ WebAuthn จะไม่แสดง UI และยังคงรอดำเนินการจนกว่าผู้ใช้จะเลือกบัญชีเพื่อลงชื่อเข้าใช้จากคำแนะนำของการป้อนข้อความอัตโนมัติ หากผู้ใช้เลือกพาสคีย์ เบราว์เซอร์จะแก้คำมั่นสัญญาด้วยข้อมูลเข้าสู่ระบบแทนการกรอกแบบฟอร์มลงชื่อเข้าใช้ ดังนั้นจึงเป็นหน้าที่ของหน้าที่จะต้องลงชื่อเข้าใช้ให้ผู้ใช้
ใส่คำอธิบายประกอบในช่องป้อนข้อมูลแบบฟอร์ม
เพิ่มแอตทริบิวต์ autocomplete
ลงในช่องชื่อผู้ใช้ input
หากจำเป็น
เพิ่ม username
และ webauthn
เป็นโทเค็นต่อท้ายเพื่อให้แนะนำพาสคีย์
<input type="text" name="username" autocomplete="username webauthn" ...>
การตรวจหาฟีเจอร์
ก่อนเรียกใช้การเรียก WebAuthn API แบบมีเงื่อนไข ให้ตรวจสอบดังนี้
- เบราว์เซอร์รองรับ WebAuthn
- เบราว์เซอร์รองรับ UI แบบมีเงื่อนไขของ WebAuthn
// Availability of `window.PublicKeyCredential` means WebAuthn is usable.
if (window.PublicKeyCredential &&
PublicKeyCredential.isConditionalMediationAvailable) {
// Check if conditional mediation is available.
const isCMA = await PublicKeyCredential.isConditionalMediationAvailable();
if (isCMA) {
// Call WebAuthn authentication
}
}
เรียกการทดสอบจากเซิร์ฟเวอร์ RP
ดึงข้อมูลการท้าทายจากเซิร์ฟเวอร์ RP ที่ต้องใช้ในการเรียก
navigator.credentials.get()
:
challenge
: ระบบทดสอบที่เซิร์ฟเวอร์สร้างขึ้นใน ArrayBuffer ซึ่งจำเป็นต่อการป้องกัน การโจมตีจากการเล่นซ้ำ โปรดสร้างชาเลนจ์ใหม่ทุกครั้งที่ลงชื่อเข้าใช้ และข้ามคำถามนั้นไปเมื่อผ่านไประยะเวลาหนึ่งหรือหลังจากพยายามลงชื่อเข้าใช้ไม่สำเร็จ ให้มองว่านี่คือโทเค็น CSRFallowCredentials
: อาร์เรย์ของข้อมูลเข้าสู่ระบบที่ยอมรับได้สำหรับการตรวจสอบสิทธิ์นี้ ส่งอาร์เรย์ว่างเพื่อให้ผู้ใช้เลือกพาสคีย์ที่ใช้ได้จากรายการที่แสดงโดยเบราว์เซอร์userVerification
: ระบุว่าการยืนยันผู้ใช้โดยใช้การล็อกหน้าจออุปกรณ์คือ"required"
,"preferred"
หรือ"discouraged"
ค่าเริ่มต้นคือ"preferred"
ซึ่งหมายความว่า Authenticator อาจข้ามการยืนยันผู้ใช้ ตั้งค่านี้เป็น"preferred"
หรือละเว้นพร็อพเพอร์ตี้
เรียกใช้ WebAuthn API ด้วยแฟล็ก conditional
เพื่อตรวจสอบสิทธิ์ผู้ใช้
เรียกใช้ navigator.credentials.get()
เพื่อเริ่มรอการตรวจสอบสิทธิ์ผู้ใช้
// To abort a WebAuthn call, instantiate an `AbortController`.
const abortController = new AbortController();
const publicKeyCredentialRequestOptions = {
// Server generated challenge
challenge: ****,
// The same RP ID as used during registration
rpId: 'example.com',
};
const credential = await navigator.credentials.get({
publicKey: publicKeyCredentialRequestOptions,
signal: abortController.signal,
// Specify 'conditional' to activate conditional UI
mediation: 'conditional'
});
rpId
: รหัส RP คือโดเมนและเว็บไซต์สามารถระบุโดเมนของตนหรือส่วนต่อท้ายที่ลงทะเบียนได้ ค่านี้ต้องตรงกับ rp.id ที่ใช้เมื่อสร้างพาสคีย์
อย่าลืมระบุ mediation: 'conditional'
เพื่อทำให้คำขอมีเงื่อนไข
ส่งข้อมูลเข้าสู่ระบบคีย์สาธารณะที่ส่งคืนไปยังเซิร์ฟเวอร์ RP
หลังจากที่ผู้ใช้เลือกบัญชีและให้ความยินยอมโดยใช้การล็อกหน้าจอของอุปกรณ์แล้ว สัญญาจะยุติการแสดงออบเจ็กต์ PublicKeyCredential
ไปยังฟรอนท์เอนด์ของ RP
สัญญาอาจถูกปฏิเสธด้วยเหตุผลหลายประการ คุณจะต้องจัดการข้อผิดพลาดตามนั้น ขึ้นอยู่กับพร็อพเพอร์ตี้ name
ของออบเจ็กต์ Error
ดังนี้
NotAllowedError
: ผู้ใช้ยกเลิกการดำเนินการ- ข้อยกเว้นอื่นๆ: มีบางอย่างที่ไม่คาดคิดเกิดขึ้น เบราว์เซอร์จะแสดงกล่องโต้ตอบ ข้อผิดพลาดแก่ผู้ใช้
ออบเจ็กต์ข้อมูลเข้าสู่ระบบคีย์สาธารณะมีพร็อพเพอร์ตี้ต่อไปนี้
id
: รหัสที่เข้ารหัส base64url ของข้อมูลเข้าสู่ระบบพาสคีย์ที่ตรวจสอบสิทธิ์แล้วrawId
: รหัสข้อมูลเข้าสู่ระบบเวอร์ชัน ArrayBufferresponse.clientDataJSON
: ArrayBuffer ของข้อมูลไคลเอ็นต์ ช่องนี้มีข้อมูล เช่น ภารกิจและต้นทางที่เซิร์ฟเวอร์ RP จะต้องยืนยันresponse.authenticatorData
: ArrayBuffer ของข้อมูล Authenticator ช่องนี้มีข้อมูล เช่น รหัส RPresponse.signature
: ArrayBuffer ของลายเซ็น ค่านี้เป็นหัวใจสำคัญของข้อมูลเข้าสู่ระบบและต้องได้รับการยืนยันบนเซิร์ฟเวอร์response.userHandle
: ArrayBuffer ที่มีรหัสผู้ใช้ที่ตั้งค่าไว้ตอนสร้าง คุณจะใช้ค่านี้แทนรหัสข้อมูลเข้าสู่ระบบได้หากเซิร์ฟเวอร์ต้องเลือกค่ารหัสที่จะใช้ หรือหากแบ็กเอนด์ไม่ต้องการสร้างดัชนีในรหัสข้อมูลเข้าสู่ระบบauthenticatorAttachment
: ส่งคืนplatform
เมื่อมีข้อมูลเข้าสู่ระบบนี้มาจากอุปกรณ์ในเครือข่ายเดียวกัน มิเช่นนั้น จะเป็นcross-platform
โดยเฉพาะเมื่อผู้ใช้ใช้โทรศัพท์ในการลงชื่อเข้าใช้ หากผู้ใช้ต้องการใช้โทรศัพท์ในการลงชื่อเข้าใช้ ลองแจ้งให้ผู้ใช้สร้างพาสคีย์ในอุปกรณ์ในท้องถิ่นtype
: ช่องนี้ตั้งค่าเป็น"public-key"
เสมอ
หากคุณใช้ไลบรารีในการจัดการออบเจ็กต์ข้อมูลเข้าสู่ระบบคีย์สาธารณะในเซิร์ฟเวอร์ RP เราขอแนะนำให้คุณส่งทั้งออบเจ็กต์ไปยังเซิร์ฟเวอร์หลังจากเข้ารหัสบางส่วนด้วย base64url
ยืนยันลายเซ็น
เมื่อได้รับข้อมูลเข้าสู่ระบบคีย์สาธารณะบนเซิร์ฟเวอร์ ให้ส่งไปยังไลบรารี FIDO เพื่อประมวลผลออบเจ็กต์
ค้นหารหัสข้อมูลเข้าสู่ระบบที่ตรงกันกับพร็อพเพอร์ตี้ id
(หากต้องการระบุบัญชีผู้ใช้ ให้ใช้พร็อพเพอร์ตี้ userHandle
ซึ่งก็คือ user.id
ที่คุณระบุเมื่อสร้างข้อมูลเข้าสู่ระบบ) ดูว่ายืนยัน signature
ของข้อมูลเข้าสู่ระบบด้วยคีย์สาธารณะที่จัดเก็บไว้ได้หรือไม่ ในการทำเช่นนี้ เราขอแนะนำให้ใช้ไลบรารีฝั่งเซิร์ฟเวอร์หรือโซลูชันแทนการเขียนโค้ดของคุณเอง คุณจะหาไลบรารีโอเพนซอร์สได้ในที่เก็บ GitHub แบบ Webauth
เมื่อยืนยันข้อมูลเข้าสู่ระบบด้วยคีย์สาธารณะที่ตรงกันแล้ว ให้ลงชื่อเข้าใช้