พาสคีย์ทำให้บัญชีผู้ใช้ปลอดภัยขึ้น ใช้งานง่ายขึ้น
การใช้พาสคีย์แทนรหัสผ่านเป็นวิธีที่ยอดเยี่ยมสำหรับเว็บไซต์ในการทำให้บัญชีผู้ใช้ปลอดภัยขึ้น ใช้งานง่ายขึ้น ใช้งานได้ง่ายขึ้น และไม่ต้องใช้รหัสผ่าน เมื่อใช้พาสคีย์ ผู้ใช้จะลงชื่อเข้าใช้เว็บไซต์หรือแอปได้โดยใช้เพียงลายนิ้วมือ ใบหน้า หรือ PIN ของอุปกรณ์
คุณต้องสร้างพาสคีย์ที่เชื่อมโยงกับบัญชีผู้ใช้และจัดเก็บคีย์สาธารณะไว้ในเซิร์ฟเวอร์ก่อน ผู้ใช้จึงจะลงชื่อเข้าใช้ด้วยพาสคีย์ได้
วิธีการทำงาน
ระบบอาจขอให้ผู้ใช้สร้างพาสคีย์ในสถานการณ์ต่อไปนี้
- เมื่อผู้ใช้ลงชื่อเข้าใช้โดยใช้รหัสผ่าน
- เมื่อผู้ใช้ลงชื่อเข้าใช้โดยใช้พาสคีย์จากอุปกรณ์เครื่องอื่น (นั่นคือ
authenticatorAttachment
เท่ากับcross-platform
) - ในหน้าเฉพาะที่ผู้ใช้จัดการพาสคีย์ได้
หากต้องการสร้างพาสคีย์ คุณต้องใช้ WebAuthn API
ขั้นตอนการลงทะเบียนพาสคีย์มีองค์ประกอบ 4 อย่างดังนี้
- แบ็กเอนด์: เซิร์ฟเวอร์แบ็กเอนด์ที่มีฐานข้อมูลบัญชีที่จัดเก็บคีย์สาธารณะและข้อมูลเมตาอื่นๆ เกี่ยวกับพาสคีย์
- หน้าเว็บ: หน้าเว็บที่สื่อสารกับเบราว์เซอร์และส่งคำขอดึงข้อมูลไปยังแบ็กเอนด์
- เบราว์เซอร์: เบราว์เซอร์ของผู้ใช้ที่เรียกใช้ JavaScript
- โปรแกรมตรวจสอบสิทธิ์: โปรแกรมตรวจสอบสิทธิ์ของผู้ใช้ที่สร้างและจัดเก็บพาสคีย์ ซึ่งอาจรวมถึงเครื่องมือจัดการรหัสผ่านในอุปกรณ์เดียวกับเบราว์เซอร์ (เช่น เมื่อใช้ Windows Hello) หรือในอุปกรณ์อื่น เช่น โทรศัพท์
ขั้นตอนในการเพิ่มพาสคีย์ใหม่ลงในบัญชีผู้ใช้ที่มีอยู่มีดังนี้
- ผู้ใช้ลงชื่อเข้าใช้เว็บไซต์
- เมื่อลงชื่อเข้าใช้แล้ว ผู้ใช้จะสร้างพาสคีย์ในหน้าเว็บได้ เช่น โดยการกดปุ่ม "สร้างพาสคีย์"
- ฟรอนท์เอนด์จะขอข้อมูลจากแบ็กเอนด์เพื่อสร้างพาสคีย์ เช่น ข้อมูลผู้ใช้ คำถาม และรหัสข้อมูลเข้าสู่ระบบที่จะยกเว้น
- หน้าเว็บเรียก
navigator.credentials.create()
เพื่อสร้างพาสคีย์ การเรียกนี้จะแสดงผลลัพธ์เป็นสัญญา - ระบบจะสร้างพาสคีย์หลังจากที่ผู้ใช้ให้ความยินยอมโดยใช้ล็อกหน้าจอของอุปกรณ์ สัญญาจะได้รับการแก้ไขและระบบจะส่งข้อมูลเข้าสู่ระบบคีย์สาธารณะไปยังฟรอนท์เอนด์
- ฟีดด้านหน้าจะส่งข้อมูลเข้าสู่ระบบคีย์สาธารณะไปยังแบ็กเอนด์และจัดเก็บรหัสข้อมูลเข้าสู่ระบบและคีย์สาธารณะที่เชื่อมโยงกับบัญชีผู้ใช้สำหรับการตรวจสอบสิทธิ์ในอนาคต
ความเข้ากันได้
เบราว์เซอร์ส่วนใหญ่รองรับ WebAuthn อยู่ แต่ก็ยังมีช่องโหว่เล็กน้อย โปรดดูหัวข้อการรองรับอุปกรณ์ - passkeys.dev เพื่อดูว่าเบราว์เซอร์และระบบปฏิบัติการใดบ้างที่รองรับการสร้างพาสคีย์
สร้างพาสคีย์ใหม่
ต่อไปนี้เป็นวิธีที่ส่วนหน้าควรทำงานเมื่อได้รับคำขอสร้างพาสคีย์ใหม่
การตรวจหาองค์ประกอบ
ก่อนแสดงปุ่ม "สร้างพาสคีย์ใหม่" ให้ตรวจสอบว่า
- เบราว์เซอร์รองรับ WebAuthn ด้วย
PublicKeyCredential
- อุปกรณ์รองรับโปรแกรมตรวจสอบสิทธิ์ของแพลตฟอร์ม (สร้างพาสคีย์และตรวจสอบสิทธิ์ด้วยพาสคีย์ได้) ด้วย
PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable()
- เบราว์เซอร์รองรับ WebAuthn conditional
UI ด้วย
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 จะแสดงผลเป็น Promise ซึ่งรอการโต้ตอบของผู้ใช้โดยแสดงกล่องโต้ตอบแบบโมดอล
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 ต้องการโปรแกรมตรวจสอบสิทธิ์ของแพลตฟอร์ม (โปรแกรมตรวจสอบสิทธิ์ที่ฝังอยู่ในอุปกรณ์แพลตฟอร์ม) ซึ่งจะไม่แจ้งให้เสียบ เช่น คีย์ความปลอดภัยแบบ USB ผู้ใช้มีตัวเลือกที่ง่ายกว่าในการสร้างพาสคีย์authenticatorSelection.requireResidentKey
: ตั้งค่าเป็นบูลีน "จริง" ข้อมูลเข้าสู่ระบบที่ค้นพบได้ (คีย์ที่อยู่ในเครื่อง) จะจัดเก็บข้อมูลผู้ใช้ไว้ในพาสคีย์และอนุญาตให้ผู้ใช้เลือกบัญชีเมื่อตรวจสอบสิทธิ์ ดูข้อมูลเพิ่มเติมเกี่ยวกับข้อมูลเข้าสู่ระบบที่ค้นพบได้ที่หัวข้อเจาะลึกข้อมูลเข้าสู่ระบบที่ค้นพบได้authenticatorSelection.userVerification
: ระบุว่าการยืนยันผู้ใช้โดยใช้การล็อกหน้าจอของอุปกรณ์เป็น"required"
,"preferred"
หรือ"discouraged"
ค่าเริ่มต้นคือ"preferred"
ซึ่งหมายความว่าโปรแกรมตรวจสอบสิทธิ์อาจข้ามการยืนยันผู้ใช้ ตั้งค่าเป็น"preferred"
หรือละเว้นพร็อพเพอร์ตี้นี้
ส่งข้อมูลเข้าสู่ระบบคีย์สาธารณะที่ส่งคืนไปยังแบ็กเอนด์
หลังจากที่ผู้ใช้ยินยอมโดยใช้การล็อกหน้าจอของอุปกรณ์ ระบบจะสร้างพาสคีย์และแก้ปัญหาสัญญาสำเร็จโดยส่งออบเจ็กต์ PublicKeyCredential ไปยังฟรอนท์เอนด์
การปฏิเสธคำมั่นสัญญาอาจเกิดขึ้นได้จากหลายสาเหตุ คุณจัดการข้อผิดพลาดเหล่านี้ได้โดยตรวจสอบพร็อพเพอร์ตี้ name
ของออบเจ็กต์ Error
ดังนี้
InvalidStateError
: มีพาสคีย์อยู่ในอุปกรณ์อยู่แล้ว ระบบจะไม่แสดงกล่องโต้ตอบข้อผิดพลาดให้ผู้ใช้เห็นและเว็บไซต์ไม่ควรถือว่านี่เป็นข้อผิดพลาด เนื่องจากผู้ใช้ต้องการให้มีการลงทะเบียนอุปกรณ์ในระบบและเป็นเช่นนั้นNotAllowedError
: ผู้ใช้ยกเลิกการดำเนินการ- ข้อยกเว้นอื่นๆ: เกิดข้อผิดพลาดที่ไม่คาดคิด เบราว์เซอร์จะแสดงกล่องโต้ตอบแสดงข้อผิดพลาดให้ผู้ใช้เห็น
ออบเจ็กต์ข้อมูลเข้าสู่ระบบด้วยคีย์สาธารณะมีพร็อพเพอร์ตี้ต่อไปนี้
id
: รหัสที่เข้ารหัส Base64URL ของพาสคีย์ที่สร้างขึ้น รหัสนี้ช่วยให้เบราว์เซอร์ทราบว่ามีพาสคีย์ที่ตรงกันในอุปกรณ์หรือไม่เมื่อตรวจสอบสิทธิ์ ต้องเก็บค่านี้ไว้ในฐานข้อมูลในแบ็กเอนด์rawId
: รหัสข้อมูลเข้าสู่ระบบเวอร์ชัน ArrayBufferresponse.clientDataJSON
: ข้อมูลไคลเอ็นต์ที่เข้ารหัส ArrayBufferresponse.attestationObject
: ออบเจ็กต์เอกสารรับรองที่เข้ารหัส ArrayBuffer ซึ่งประกอบด้วยข้อมูลสำคัญ เช่น รหัส RP, Flag และคีย์สาธารณะauthenticatorAttachment
: แสดงผล"platform"
เมื่อสร้างข้อมูลเข้าสู่ระบบนี้ในอุปกรณ์ที่ใช้พาสคีย์ได้type
: ฟิลด์นี้จะตั้งค่าเป็น"public-key"
เสมอ
หากคุณใช้ไลบรารีในการจัดการออบเจ็กต์ข้อมูลเข้าสู่ระบบคีย์สาธารณะในแบ็กเอนด์ เราขอแนะนำให้ส่งออบเจ็กต์ทั้งหมดไปยังแบ็กเอนด์หลังจากเข้ารหัสออบเจ็กต์บางส่วนด้วย base64url
บันทึกข้อมูลเข้าสู่ระบบ
เมื่อได้รับข้อมูลเข้าสู่ระบบคีย์สาธารณะในแบ็กเอนด์ ให้ส่งข้อมูลดังกล่าวไปยังไลบรารี FIDO เพื่อประมวลผลออบเจ็กต์
จากนั้นคุณสามารถจัดเก็บข้อมูลที่ดึงมาจากข้อมูลเข้าสู่ระบบไว้ในฐานข้อมูลเพื่อใช้ในอนาคต รายการต่อไปนี้มีพร็อพเพอร์ตี้ทั่วไปที่ควรบันทึก
- รหัสเข้าสู่ระบบ (คีย์หลัก)
- User ID
- คีย์สาธารณะ
ข้อมูลเข้าสู่ระบบด้วยคีย์สาธารณะยังมีข้อมูลต่อไปนี้ด้วยซึ่งคุณอาจต้องการบันทึกไว้ในฐานข้อมูล
- การแจ้งการมีสิทธิ์สำรองข้อมูล:
true
หากอุปกรณ์มีสิทธิ์สำหรับการซิงค์ข้อมูลพาสคีย์ - สถานะการสำรองข้อมูล
flag:
true
หากตั้งค่าพาสคีย์ที่สร้างขึ้นให้ซิงค์จริง - การขนส่ง:
รายการการขนส่งที่อุปกรณ์รองรับ
"internal"
หมายความว่าอุปกรณ์รองรับพาสคีย์ ส่วน"hybrid"
หมายความว่าอุปกรณ์รองรับการตรวจสอบสิทธิ์ในอุปกรณ์อีกเครื่องด้วย
ทำตามวิธีการโดยละเอียดที่การลงทะเบียนพาสคีย์ฝั่งเซิร์ฟเวอร์
หากต้องการตรวจสอบสิทธิ์ผู้ใช้ โปรดอ่านลงชื่อเข้าใช้ด้วยพาสคีย์ผ่านการป้อนข้อความอัตโนมัติของแบบฟอร์ม