พาสคีย์ทำให้บัญชีผู้ใช้ปลอดภัยขึ้น เรียบง่ายขึ้น และใช้งานง่ายขึ้น
การใช้พาสคีย์แทนรหัสผ่านเป็นวิธีที่ยอดเยี่ยมสำหรับเว็บไซต์ในการทำให้บัญชีผู้ใช้ปลอดภัยยิ่งขึ้น ใช้งานง่ายขึ้น และไม่ใช้รหัสผ่าน เมื่อใช้พาสคีย์ ผู้ใช้จะลงชื่อเข้าใช้เว็บไซต์หรือแอปได้โดยใช้ลายนิ้วมือ ใบหน้า หรือ PIN ของอุปกรณ์
คุณต้องสร้างพาสคีย์โดยเชื่อมโยงกับบัญชีผู้ใช้ และจัดเก็บคีย์สาธารณะไว้ในเซิร์ฟเวอร์ก่อนที่ผู้ใช้จะลงชื่อเข้าใช้ด้วยรหัสผ่านดังกล่าวได้
วิธีการทำงาน
ระบบอาจขอให้ผู้ใช้สร้างพาสคีย์ในสถานการณ์ใดกรณีหนึ่งต่อไปนี้
- เมื่อผู้ใช้ลงชื่อเข้าใช้ด้วยรหัสผ่าน
- เมื่อผู้ใช้ลงชื่อเข้าใช้ด้วยพาสคีย์จากอุปกรณ์อื่น (ซึ่งก็คือ
authenticatorAttachment
คือcross-platform
) - ในหน้าเฉพาะที่ผู้ใช้จัดการพาสคีย์ได้
หากต้องการสร้างพาสคีย์ ให้ใช้ WebAuthn API
ขั้นตอนการลงทะเบียนพาสคีย์มีองค์ประกอบ 4 อย่างดังนี้
- แบ็กเอนด์: เซิร์ฟเวอร์แบ็กเอนด์ของคุณที่จัดเก็บฐานข้อมูลบัญชีซึ่งจัดเก็บคีย์สาธารณะและข้อมูลเมตาอื่นๆ เกี่ยวกับพาสคีย์
- ฟรอนท์เอนด์: ฟรอนท์เอนด์ที่สื่อสารกับเบราว์เซอร์และส่งคำขอดึงข้อมูลไปยังแบ็กเอนด์
- เบราว์เซอร์: เบราว์เซอร์ของผู้ใช้ที่เรียกใช้ JavaScript
- Authenticator: Authenticator ของผู้ใช้ที่สร้างและจัดเก็บพาสคีย์ โดยอาจรวมถึงเครื่องมือจัดการรหัสผ่านบนอุปกรณ์เดียวกับเบราว์เซอร์ (เช่น เมื่อใช้ Windows Hello) หรือในอุปกรณ์อื่น เช่น โทรศัพท์
![แผนภาพการลงทะเบียนพาสคีย์](https://web.dev/static/articles/passkey-registration/image/passkey-registration-diagram.png?authuser=1&hl=th)
วิธีเพิ่มพาสคีย์ใหม่ลงในบัญชีผู้ใช้ที่มีอยู่มีดังนี้
- ผู้ใช้ลงชื่อเข้าใช้เว็บไซต์
- เมื่อลงชื่อเข้าใช้แล้ว ผู้ใช้จะขอสร้างพาสคีย์ในฟรอนท์เอนด์ เช่น โดยการกดปุ่ม "สร้างพาสคีย์"
- ฟรอนท์เอนด์จะขอข้อมูลจากแบ็กเอนด์เพื่อสร้างพาสคีย์ เช่น ข้อมูลผู้ใช้ คำถาม และรหัสข้อมูลเข้าสู่ระบบที่จะยกเว้น
- ฟรอนท์เอนด์จะโทรหา
navigator.credentials.create()
เพื่อสร้างพาสคีย์ การโทรครั้งนี้ถือเป็นการสัญญา - ระบบจะสร้างพาสคีย์หลังจากผู้ใช้ให้ความยินยอมโดยใช้การล็อกหน้าจอของอุปกรณ์ สัญญาจะได้รับการแก้ไขและระบบจะส่งข้อมูลเข้าสู่ระบบคีย์สาธารณะไปยังฟรอนท์เอนด์
- ฟรอนท์เอนด์จะส่งข้อมูลเข้าสู่ระบบคีย์สาธารณะไปยังแบ็กเอนด์และจัดเก็บรหัสข้อมูลเข้าสู่ระบบและคีย์สาธารณะที่เชื่อมโยงกับบัญชีผู้ใช้เพื่อการตรวจสอบสิทธิ์ในอนาคต
ความเข้ากันได้
เบราว์เซอร์ส่วนใหญ่รองรับ WebAuthn อยู่ แต่ก็ยังมีช่องโหว่เล็กน้อย โปรดดูการรองรับอุปกรณ์ -พาสคีย์s.dev เพื่อดูว่าชุดเบราว์เซอร์และระบบปฏิบัติการรองรับการสร้างพาสคีย์อย่างไร
สร้างพาสคีย์ใหม่
ฟรอนท์เอนด์ควรดำเนินการต่อไปนี้ตามคำขอให้สร้างพาสคีย์ใหม่
การตรวจหาฟีเจอร์
ก่อนแสดงปุ่ม "สร้างพาสคีย์ใหม่" ให้ตรวจสอบว่า
- เบราว์เซอร์รองรับ WebAuthn กับ
PublicKeyCredential
- อุปกรณ์รองรับตัวตรวจสอบสิทธิ์แพลตฟอร์ม (สร้างพาสคีย์และตรวจสอบสิทธิ์ด้วยพาสคีย์ได้) ด้วย
PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable()
- เบราว์เซอร์รองรับ UI แบบมีเงื่อนไขของ WebAuthn กับ
PublicKeyCredenital.isConditionalMediationAvailable()
// Availability of `window.PublicKeyCredential` means WebAuthn is usable.
// `isUserVerifyingPlatformAuthenticatorAvailable` means the feature detection is usable.
// `isConditionalMediationAvailable` means the feature detection is usable.
if (window.PublicKeyCredential &&
PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable &&
PublicKeyCredential.isConditionalMediationAvailable) {
// Check if user verifying platform authenticator is available.
Promise.all([
PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable(),
PublicKeyCredential.isConditionalMediationAvailable(),
]).then(results => {
if (results.every(r => r === true)) {
// Display "Create a new passkey" button
}
});
}
เบราว์เซอร์นี้ไม่รองรับพาสคีย์จนกว่าจะเป็นไปตามเงื่อนไขทั้งหมด ปุ่ม "สร้างพาสคีย์ใหม่" ยังไม่ควรปรากฏจนกว่าจะถึงเวลาดังกล่าว
ดึงข้อมูลสำคัญจากแบ็กเอนด์
เมื่อผู้ใช้คลิกปุ่ม ให้ดึงข้อมูลสำคัญเพื่อเรียกใช้ navigator.credentials.create()
จากแบ็กเอนด์ ดังนี้
challenge
: ความท้าทายที่เซิร์ฟเวอร์สร้างขึ้นใน ArrayBuffer สำหรับการลงทะเบียนนี้ ซึ่งจำเป็นแต่ไม่มีการใช้งานในระหว่างการลงทะเบียน เว้นแต่จะทำเอกสารรับรอง ซึ่งเป็นหัวข้อขั้นสูงที่ไม่ได้กล่าวถึงที่นี่user.id
: รหัสที่ไม่ซ้ำกันของผู้ใช้ ค่านี้ต้องเป็น ArrayBuffer ซึ่งไม่มีข้อมูลส่วนบุคคลที่ระบุตัวบุคคลนั้นได้ เช่น อีเมลหรือชื่อผู้ใช้ ค่า 16 ไบต์ที่สร้างขึ้นแบบสุ่มสำหรับแต่ละบัญชีจะสามารถใช้งานได้ดีuser.name
: ช่องนี้ควรมีตัวระบุที่ไม่ซ้ำกันสำหรับบัญชีที่ผู้ใช้จะจดจำได้ เช่น อีเมลหรือชื่อผู้ใช้ ข้อมูลนี้จะแสดง ในตัวเลือกบัญชี (หากใช้ชื่อผู้ใช้ ให้ใช้ค่าเดียวกับในการตรวจสอบสิทธิ์รหัสผ่าน)user.displayName
: ช่องนี้เป็นชื่อที่ต้องใช้งานและเข้าใจง่ายกว่าสำหรับบัญชี ชื่อต้องไม่ซ้ำและอาจเป็นชื่อที่ผู้ใช้เลือก หากเว็บไซต์ไม่มีค่าที่เหมาะสมจะใส่ที่นี่ ให้ส่งสตริงว่าง ข้อมูลนี้จะแสดงบนตัวเลือกบัญชี โดยขึ้นอยู่กับเบราว์เซอร์excludeCredentials
: ป้องกันการลงทะเบียนอุปกรณ์เครื่องเดียวกันด้วยการระบุรายการรหัสข้อมูลเข้าสู่ระบบที่ลงทะเบียนแล้ว สมาชิกtransports
(หากระบุไว้) ควรมีผลของการเรียกใช้getTransports()
ระหว่างการลงทะเบียนของข้อมูลเข้าสู่ระบบแต่ละรายการ
เรียกใช้ WebAuthn API เพื่อสร้างพาสคีย์
โทรติดต่อ navigator.credentials.create()
เพื่อสร้างพาสคีย์ใหม่ API จะให้ผลลัพธ์ข้อความสัญญา ซึ่งกำลังรอการโต้ตอบของผู้ใช้เพื่อแสดงกล่องโต้ตอบโมดัล
const publicKeyCredentialCreationOptions = {
challenge: *****,
rp: {
name: "Example",
id: "example.com",
},
user: {
id: *****,
name: "john78",
displayName: "John",
},
pubKeyCredParams: [{alg: -7, type: "public-key"},{alg: -257, type: "public-key"}],
excludeCredentials: [{
id: *****,
type: 'public-key',
transports: ['internal'],
}],
authenticatorSelection: {
authenticatorAttachment: "platform",
requireResidentKey: true,
}
};
const credential = await navigator.credentials.create({
publicKey: publicKeyCredentialCreationOptions
});
// Encode and send the credential to the server for verification.
พารามิเตอร์ที่ไม่ได้อธิบายไว้ข้างต้นมีดังนี้
rp.id
: รหัส RP คือโดเมนและเว็บไซต์จะระบุโดเมนหรือคำต่อท้ายที่จดทะเบียนได้ เช่น หากต้นทางของ RP คือhttps://login.example.com:1337
รหัส RP อาจเป็นlogin.example.com
หรือexample.com
หากระบุรหัส RP เป็นexample.com
ผู้ใช้จะตรวจสอบสิทธิ์ในlogin.example.com
หรือโดเมนย่อยในexample.com
ได้rp.name
: ชื่อ RPpubKeyCredParams
: ช่องนี้ระบุอัลกอริทึมคีย์สาธารณะที่ RP รองรับ เราขอแนะนำให้ ตั้งค่าเป็น[{alg: -7, type: "public-key"},{alg: -257, type: "public-key"}]
ซึ่งระบุการรองรับ ECDSA ที่มี P-256 และ RSA PKCS#1 รวมถึงการรองรับเหตุการณ์เหล่านี้จึงครอบคลุมโดยสมบูรณ์authenticatorSelection.authenticatorAttachment
: ตั้งค่าเป็น"platform"
หากการสร้างพาสคีย์นี้เป็นการอัปเกรดจากรหัสผ่าน เช่น ในโปรโมชันหลังจากลงชื่อเข้าใช้"platform"
ระบุว่า RP ต้องการ Authenticator สำหรับแพลตฟอร์ม (Authenticator ที่ฝังอยู่ในอุปกรณ์แพลตฟอร์ม) ซึ่งจะไม่แสดงข้อความแจ้งให้เสียบ เช่น คีย์ความปลอดภัย USB ผู้ใช้มีตัวเลือกที่ง่ายกว่าในการสร้างพาสคีย์authenticatorSelection.requireResidentKey
: ตั้งค่าเป็นบูลีน "true" ข้อมูลเข้าสู่ระบบที่ค้นพบได้ (คีย์ผู้พำนักอาศัย) จะเก็บข้อมูลผู้ใช้ไว้ในพาสคีย์และช่วยให้ผู้ใช้เลือกบัญชีได้เมื่อทำการตรวจสอบสิทธิ์ ดูข้อมูลเพิ่มเติมเกี่ยวกับข้อมูลเข้าสู่ระบบที่ค้นพบได้ที่หัวข้อเจาะลึกข้อมูลเข้าสู่ระบบที่ค้นพบได้authenticatorSelection.userVerification
: ระบุว่าการยืนยันผู้ใช้โดยใช้การล็อกหน้าจออุปกรณ์คือ"required"
,"preferred"
หรือ"discouraged"
ค่าเริ่มต้นคือ"preferred"
ซึ่งหมายความว่า Authenticator อาจข้ามการยืนยันผู้ใช้ โปรดตั้งค่าเป็น"preferred"
หรือไม่ใช้พร็อพเพอร์ตี้นี้
ส่งข้อมูลเข้าสู่ระบบคีย์สาธารณะที่ส่งคืนไปยังแบ็กเอนด์
หลังจากที่ผู้ใช้ยินยอมโดยใช้การล็อกหน้าจอของอุปกรณ์ ระบบจะสร้างพาสคีย์และแก้ปัญหาสัญญาสำเร็จโดยส่งออบเจ็กต์ PublicKeyCredential ไปยังฟรอนท์เอนด์
การสัญญาอาจถูกปฏิเสธด้วยเหตุผลหลายประการ คุณจัดการข้อผิดพลาดเหล่านี้ได้โดยตรวจสอบพร็อพเพอร์ตี้ name
ของออบเจ็กต์ Error
ดังนี้
InvalidStateError
: มีพาสคีย์ในอุปกรณ์อยู่แล้ว ระบบจะไม่แสดงกล่องโต้ตอบข้อผิดพลาดให้ผู้ใช้เห็นและเว็บไซต์ไม่ควรถือว่านี่เป็นข้อผิดพลาด เนื่องจากผู้ใช้ต้องการให้มีการลงทะเบียนอุปกรณ์ในระบบและเป็นเช่นนั้นNotAllowedError
: ผู้ใช้ยกเลิกการดำเนินการ- ข้อยกเว้นอื่นๆ: เกิดข้อผิดพลาดที่ไม่คาดคิด เบราว์เซอร์จะแสดง กล่องโต้ตอบข้อผิดพลาดให้ผู้ใช้เห็น
ออบเจ็กต์ข้อมูลเข้าสู่ระบบคีย์สาธารณะจะมีพร็อพเพอร์ตี้ต่อไปนี้
id
: รหัสที่เข้ารหัส Base64URL ของพาสคีย์ที่สร้างขึ้น รหัสนี้ช่วยให้เบราว์เซอร์ระบุได้ว่าพาสคีย์ที่ตรงกันอยู่ในอุปกรณ์หรือไม่ขณะตรวจสอบสิทธิ์ ต้องเก็บค่านี้ไว้ในฐานข้อมูลในแบ็กเอนด์rawId
: รหัสข้อมูลเข้าสู่ระบบเวอร์ชัน ArrayBufferresponse.clientDataJSON
: ข้อมูลไคลเอ็นต์ที่เข้ารหัสใน ArrayBufferresponse.attestationObject
: ออบเจ็กต์เอกสารรับรองที่เข้ารหัส ArrayBuffer ซึ่งมีข้อมูลสำคัญ เช่น รหัส RP, แฟล็ก และคีย์สาธารณะauthenticatorAttachment
: แสดงผล"platform"
เมื่อสร้างข้อมูลเข้าสู่ระบบนี้ในอุปกรณ์ที่ใช้พาสคีย์ได้type
: ช่องนี้จะตั้งค่าเป็น"public-key"
เสมอ
หากคุณใช้ไลบรารีในการจัดการออบเจ็กต์ข้อมูลเข้าสู่ระบบคีย์สาธารณะในแบ็กเอนด์ เราขอแนะนำให้ส่งออบเจ็กต์ทั้งหมดไปยังแบ็กเอนด์หลังจากเข้ารหัสออบเจ็กต์บางส่วนด้วย base64url
บันทึกข้อมูลเข้าสู่ระบบ
เมื่อได้รับข้อมูลเข้าสู่ระบบคีย์สาธารณะในแบ็กเอนด์แล้ว ให้ส่งต่อไปยังไลบรารี FIDO เพื่อประมวลผลออบเจ็กต์
จากนั้นคุณสามารถจัดเก็บข้อมูลที่ดึงจากข้อมูลเข้าสู่ระบบไปยังฐานข้อมูลเพื่อการใช้งานในอนาคต รายการต่อไปนี้มีพร็อพเพอร์ตี้ทั่วไปที่ควรบันทึก
- รหัสเข้าสู่ระบบ (คีย์หลัก)
- User ID
- คีย์สาธารณะ
ข้อมูลเข้าสู่ระบบคีย์สาธารณะยังมีข้อมูลต่อไปนี้ซึ่งคุณอาจต้องการบันทึกไว้ในฐานข้อมูลด้วย
- การแจ้งการมีสิทธิ์สำรองข้อมูล:
true
หากอุปกรณ์มีสิทธิ์สำหรับการซิงค์ข้อมูลพาสคีย์ - การแจ้งสถานะการสำรองข้อมูล:
true
หากมีการกำหนดให้ซิงค์พาสคีย์ที่สร้างขึ้นจริง - การขนส่ง:
รายการการขนส่งที่อุปกรณ์รองรับ:
"internal"
หมายความว่าอุปกรณ์รองรับพาสคีย์"hybrid"
หมายความว่าอุปกรณ์รองรับการตรวจสอบสิทธิ์ในอุปกรณ์อื่นด้วย
ทำตามวิธีการโดยละเอียดเพิ่มเติมที่การลงทะเบียนพาสคีย์ฝั่งเซิร์ฟเวอร์
หากต้องการตรวจสอบสิทธิ์ผู้ใช้ โปรดอ่านหัวข้อลงชื่อเข้าใช้ด้วยพาสคีย์ผ่านการป้อนแบบฟอร์มอัตโนมัติ