게시일: 2024년 11월 12일
WebAuthn Signal API를 사용하면 신뢰 당사자가 연결된 패스키 제공업체에 기존 사용자 인증 정보를 전달할 수 있습니다. 이를 통해 패스키를 지원하는 제공업체는 더 이상 사용자에게 제공되지 않도록 잘못되거나 취소된 패스키를 저장소에서 업데이트하거나 삭제할 수 있습니다.
호환성
데스크톱용 Chrome은 Chrome 132부터 Signal API를 지원합니다. Google 비밀번호 관리자는 신호를 반영하여 패스키를 업데이트할 수 있습니다. Chrome 확장 프로그램 기반 패스키 제공업체의 경우 신호를 반영할지 여부는 제공업체에 따라 다릅니다.
Android용 Chrome 지원은 추후에 제공될 예정입니다.
Safari는 지원하지만 아직 구현되지 않았습니다. Firefox는 아직 의견을 공유하지 않았습니다.
배경
패스키 (검색 가능한 사용자 인증 정보)가 생성되면 사용자 이름 및 표시 이름과 같은 메타데이터가 비공개 키와 함께 패스키 제공업체 (예: 비밀번호 관리자)에 저장되고 공개 키 사용자 인증 정보는 신뢰 당사자 (RP)의 서버에 저장됩니다. 사용자 이름과 표시 이름을 저장하면 메시지가 표시될 때 사용자가 제공된 패스키 중 어떤 패스키로 로그인할지 식별하는 데 도움이 됩니다. 이 기능은 여러 패스키 제공업체의 패스키가 2개 이상인 경우에 특히 유용합니다.
하지만 패스키 제공업체의 패스키 목록과 서버의 사용자 인증 정보 목록 간에 불일치가 발생하여 혼란이 야기되는 경우가 몇 가지 있습니다.
첫 번째 사례는 사용자가 서버에서 사용자 인증 정보를 삭제하고 패스키 제공업체의 패스키는 그대로 두는 경우입니다. 사용자가 다음에 패스키로 로그인하려고 하면 패스키 제공업체에서 패스키를 계속 사용자에게 표시합니다. 그러나 서버에서 삭제된 공개 키로 확인할 수 없으므로 로그인 시도가 실패합니다.
두 번째 경우는 사용자가 서버에서 사용자 이름 또는 표시 이름을 업데이트하는 경우입니다. 사용자가 다음에 로그인하려고 하면 패스키 제공업체의 패스키에 서버에서 업데이트된 것과는 달리 기존 사용자 이름과 표시 이름이 계속 표시됩니다. 동기화되어 있는 것이 이상적입니다.
Signal API
Signal API는 RP가 패스키 제공업체에 변경사항을 신호하여 이러한 혼란을 해결하는 WebAuthn API입니다. 다음 세 가지 방법이 있습니다.
PublicKeyCredential.signalUnknownCredential
: 사용자 인증 정보가 존재하지 않음을 나타내는 신호PublicKeyCredential.signalAllAcceptedCredentials
: 저장된 사용자 인증 정보 목록 신호PublicKeyCredential.signalCurrentUserDetails
: 업데이트된 사용자 이름 또는 표시 이름을 신호
사용자 인증 정보가 존재하지 않음을 나타내는 신호
const credential = await navigator.credentials.get({ ... });
const payload = credential.toJSON();
const result = await fetch('/login', { ... });
// Detect authentication failure due to lack of the credential
if (result.status === 404) {
// Feature detection
if (PublicKeyCredential.signalUnknownCredential) {
await PublicKeyCredential.signalUnknownCredential({
rpId: "example.com",
credentialId: "vI0qOggiE3OT01ZRWBYz5l4MEgU0c7PmAA" // base64url encoded credential ID
});
} else {
// Encourage the user to delete the passkey from the password manager nevertheless.
...
}
}
RP ID 및 사용자 인증 정보 ID를 사용하여 PublicKeyCredential.signalUnknownCredential()
를 호출하면 RP는 패스키 제공업체에 지정된 사용자 인증 정보가 삭제되었거나 존재하지 않는다고 알릴 수 있습니다. 이 신호를 처리하는 방법은 패스키 제공업체에 따라 다르지만 연결된 사용자 인증 정보가 없으므로 사용자가 패스키로 로그인하지 못하도록 연결된 패스키가 삭제될 것으로 예상됩니다.
이 API는 사용자 인증 정보가 없어 패스키 기반 로그인이 실패한 경우 호출할 수 있습니다. 이렇게 하면 RP는 사용자가 연결된 사용자 인증 정보가 없는 패스키로 로그인하려고 시도하는 것을 방지할 수 있습니다. 이 메서드는 signalAllAcceptedCredentials
과 달리 사용자 인증 정보 ID의 전체 목록을 전달할 필요가 없으므로 사용자가 인증되지 않은 경우마다 사용해야 지정된 사용자의 패스키 수를 공개하지 않도록 할 수 있습니다.
저장된 사용자 인증 정보 목록 신호
// After a user deletes a passkey or a user is signed in.
// Feature detection
if (PublicKeyCredential.signalAllAcceptedCredentials) {
await PublicKeyCredential.signalAllAcceptedCredentials({
rpId: "example.com",
userId: "M2YPl-KGnA8", // base64url encoded user ID
allAcceptedCredentialIds: [ // A list of base64url encoded credential IDs
"vI0qOggiE3OT01ZRWBYz5l4MEgU0c7PmAA",
...
]
});
}
RP ID, 사용자 ID, 저장된 사용자 인증 정보의 사용자 인증 정보 ID 목록을 사용하여 PublicKeyCredential.signalAllAcceptedCredentials()
를 호출하면 RP는 패스키 제공업체에 저장소에 남아 있는 사용자 인증 정보를 알릴 수 있습니다. 이 신호를 처리하는 방법은 패스키 제공업체에 따라 다르지만, 이 목록과 일치하지 않는 패스키는 삭제되어 사용자가 로그인 시 연결된 사용자 인증 정보가 없는 패스키를 보지 못하게 됩니다.
패스키 제공업체가 패스키 목록을 동기화할 수 있도록 이 API는 사용자가 패스키를 삭제할 때와 모든 로그인 시 RP에서 호출해야 합니다.
업데이트된 사용자 이름 및 표시 이름을 신호로 전달
// After a user updated their username and/or display name
// or a user is signed in.
// Feature detection
if (PublicKeyCredential.signalCurrentUserDetails) {
await PublicKeyCredential.signalCurrentUserDetails({
rpId: "example.com",
userId: "M2YPl-KGnA8", // base64url encoded user ID
name: "a.new.email.address@example.com", // username
displayName: "J. Doe"
});
} else {
}
RP는 RP ID, 사용자 ID, 사용자 이름, 표시 이름을 사용하여 PublicKeyCredential.signalCurrentUserDetails()
를 호출하여 패스키 제공업체에 업데이트된 사용자 정보를 알릴 수 있습니다. 이 신호를 처리하는 방법은 패스키 제공업체에 따라 다르지만 사용자가 소유한 패스키는 새 사용자 정보로 업데이트될 것으로 예상됩니다.
이 API는 패스키 제공업체가 이 정보를 서버와 동기화할 수 있도록 사용자의 사용자 이름 또는 표시 이름이 업데이트될 때, 로그인할 때마다 호출할 수 있습니다.
요약
Signal API는 예기치 않은 로그인 실패 가능성을 제거하여 더 나은 패스키 환경을 구축하는 데 도움이 됩니다. 신호 API를 사용하면 신뢰 당사자가 기존 사용자 인증 정보 목록과 메타데이터를 신호하여 패스키 제공업체의 패스키를 동기화 상태로 유지할 수 있습니다.
패스키에 대해 자세히 알아보려면 패스키를 통한 비밀번호 없는 로그인을 참고하세요.