패스키와 같은 FIDO 사용자 인증 정보는 비밀번호를 대체하는 것을 목표로 하지만, 대부분의 경우 사용자가 사용자 이름을 입력하지 않아도 됩니다. 이렇게 하면 사용자가 현재 웹사이트에 대해 보유한 패스키 목록에서 계정을 선택하여 인증할 수 있습니다.
이전 버전의 보안 키는 2단계 인증 방법으로 설계되었으며 잠재적인 사용자 인증 정보의 ID가 필요했기 때문에 사용자 이름을 입력해야 했습니다. 보안 키가 ID를 알지 못해도 찾을 수 있는 사용자 인증 정보를 검색 가능한 사용자 인증 정보라고 합니다. 현재 생성되는 대부분의 FIDO 사용자 인증 정보는 검색 가능한 사용자 인증 정보입니다. 특히 비밀번호 관리자나 최신 보안 키에 저장된 패스키가 그렇습니다.
사용자 인증 정보가 패스키 (검색 가능한 사용자 인증 정보)로 생성되도록 하려면 사용자 인증 정보를 만들 때 residentKey 및 requireResidentKey를 지정합니다.
공개 키 사용자 (RP)는 패스키 인증 중에 allowCredentials를 생략하여 검색 가능한 사용자 인증 정보를 사용할 수 있습니다. 이 경우 브라우저 또는 시스템은 생성 시 설정된 user.name 속성으로 식별되는 사용 가능한 패스키 목록을 사용자에게 표시합니다. 사용자가 하나를 선택하면 user.id 값이 결과 서명에 포함됩니다. 그러면 서버는 입력된 사용자 이름 대신 이 ID 또는 반환된 사용자 인증 정보 ID를 사용하여 계정을 조회할 수 있습니다.
앞서 설명한 것과 같은 계정 선택기 UI에는 검색 불가능한 사용자 인증 정보가 표시되지 않습니다.
requireResidentKey 및 residentKey
패스키를 만들려면 다음과 같이 표시된 값으로 navigator.credentials.create()에서 authenticatorSelection.residentKey 및 authenticatorSelection.requireResidentKey를 지정합니다.
async function register () {
// ...
const publicKeyCredentialCreationOptions = {
// ...
authenticatorSelection: {
authenticatorAttachment: 'platform',
residentKey: 'required',
requireResidentKey: true,
}
};
const credential = await navigator.credentials.create({
publicKey: publicKeyCredentialCreationOptions
});
// This does not run until the user selects a passkey.
const credential = {};
credential.id = cred.id;
credential.rawId = cred.id; // Pass a Base64URL encoded ID string.
credential.type = cred.type;
// ...
}
residentKey:
'required': 검색 가능한 사용자 인증 정보를 만들어야 합니다. 만들 수 없는 경우NotSupportedError이 반환됩니다.'preferred': RP는 검색 가능한 사용자 인증 정보를 만드는 것을 선호하지만 검색 불가능한 사용자 인증 정보도 허용합니다.'discouraged': RP는 검색 불가능한 사용자 인증 정보를 만드는 것을 선호하지만 검색 가능한 사용자 인증 정보를 허용합니다.
requireResidentKey:
- 이 속성은 이전 버전의 사양인 WebAuthn 수준 1과의 하위 호환성을 위해 유지됩니다.
residentKey가'required'이면true로 설정하고, 그렇지 않으면false로 설정합니다.
allowCredentials
RP는 navigator.credentials.get()에서 allowCredentials를 사용하여 패스키 인증 환경을 제어할 수 있습니다. 일반적으로 패스키 인증 환경에는 세 가지 유형이 있습니다.
모달 계정 선택기 표시
검색 가능한 사용자 인증 정보를 사용하면 RP가 모달 계정 선택기를 표시하여 사용자가 로그인할 계정을 선택한 후 사용자 인증을 진행할 수 있습니다. 이는 패스키 인증 전용 버튼을 눌러 시작되는 패스키 인증 흐름에 적합합니다.
이러한 사용자 환경을 구현하려면 navigator.credentials.get()의 allowCredentials 매개변수를 생략하거나 빈 배열을 전달합니다.
async function authenticate() {
// ...
const publicKeyCredentialRequestOptions = {
// Server generated challenge:
challenge: ****,
// The same RP ID as used during registration:
rpId: 'example.com',
// You can omit `allowCredentials` as well:
allowCredentials: []
};
const credential = await navigator.credentials.get({
publicKey: publicKeyCredentialRequestOptions,
signal: abortController.signal
});
// This does not run until the user selects a passkey.
const credential = {};
credential.id = cred.id;
credential.rawId = cred.id; // Pass a Base64URL encoded ID string.
credential.type = cred.type;
// ...
}
패스키 양식 자동 완성 표시
위에서 설명한 모달 계정 선택기는 대부분의 사용자가 패스키를 사용하고 로컬 기기에서 패스키를 사용할 수 있는 경우에 잘 작동합니다. 로컬 패스키가 없는 사용자의 경우 모달 대화상자가 계속 표시되며 사용자에게 다른 기기의 패스키를 제공하라는 메시지가 표시됩니다. 사용자를 패스키로 전환하는 동안 패스키를 설정하지 않은 사용자에게는 해당 UI를 표시하지 않는 것이 좋습니다.
대신 패스키 선택은 저장된 사용자 이름 및 비밀번호와 함께 기존 로그인 양식의 입력란에 대한 자동 완성 프롬프트로 접힐 수 있습니다. 이렇게 하면 패스키가 있는 사용자는 패스키를 선택하여 로그인 양식을 '채울' 수 있고, 저장된 사용자 이름/비밀번호 쌍이 있는 사용자는 이를 선택할 수 있으며, 둘 다 없는 사용자는 사용자 이름과 비밀번호를 입력할 수 있습니다.
이 사용자 환경은 RP가 비밀번호와 패스키를 혼합하여 사용하는 마이그레이션 중일 때 이상적입니다.
이러한 사용자 환경을 구현하려면 빈 배열을 allowCredentials 속성에 전달하거나 매개변수를 생략하는 것 외에도 navigator.credentials.get()에 mediation: 'conditional'를 지정하고 HTML username 입력란에 autocomplete="username webauthn"로 주석을 달거나 password 입력란에 autocomplete="password webauthn"로 주석을 달아야 합니다.
navigator.credentials.get() 호출은 UI를 표시하지 않지만 사용자가 주석이 달린 입력란에 포커스를 맞추면 사용 가능한 패스키가 자동 완성 옵션에 포함됩니다. 사용자가 하나를 선택하면 일반 기기 잠금 해제 인증을 거치고, 그 후에만 .get()에서 반환된 프로미스가 결과와 함께 확인됩니다. 사용자가 패스키를 선택하지 않으면 프로미스가 확인되지 않습니다.
async function authenticate() {
// ...
const publicKeyCredentialRequestOptions = {
// Server generated challenge:
challenge: ****,
// The same RP ID as used during registration:
rpId: 'example.com',
// You can omit `allowCredentials` as well:
allowCredentials: []
};
const cred = await navigator.credentials.get({
publicKey: publicKeyCredentialRequestOptions,
signal: abortController.signal,
// Specify 'conditional' to activate conditional UI
mediation: 'conditional'
});
// This does not run until the user selects a passkey.
const credential = {};
credential.id = cred.id;
credential.rawId = cred.id; // Pass a Base64URL encoded ID string.
credential.type = cred.type;
// ...
}
<input type="text" name="username" autocomplete=&qu>ot;username webauthn" ...
이 사용자 환경을 빌드하는 방법은 양식 자동 완성을 통한 패스키 로그인 및 웹 앱에서 양식 자동 완성으로 패스키 구현 Codelab에서 알아볼 수 있습니다.
재인증
재인증에 패스키를 사용하는 경우와 같이 사용자의 식별자가 이미 알려진 경우도 있습니다. 이 경우 브라우저나 OS에 계정 선택기가 표시되지 않는 패스키를 사용하려고 합니다. 이렇게 하려면 allowCredentials 매개변수에 사용자 인증 정보 ID 목록을 전달하면 됩니다.
이 경우 이름이 지정된 사용자 인증 정보가 로컬에서 사용 가능한 경우 사용자에게 즉시 기기 잠금 해제 메시지가 표시됩니다. 그렇지 않으면 사용자에게 유효한 사용자 인증 정보가 있는 다른 기기 (휴대전화 또는 보안 키)를 제시하라는 메시지가 표시됩니다.
이러한 사용자 환경을 구현하려면 로그인하는 사용자의 사용자 인증 정보 ID 목록을 제공하세요. 사용자가 이미 알려져 있으므로 RP는 이를 쿼리할 수 있어야 합니다. navigator.credentials.get()의 allowCredentials 속성에 사용자 인증 정보 ID를 PublicKeyCredentialDescriptor 객체로 제공합니다.
async function authenticate() {
// ...
const publicKeyCredentialRequestOptions = {
// Server generated challenge:
challenge: ****,
// The same RP ID as used during registration:
rpId: 'example.com',
// Provide a list of PublicKeyCredentialDescriptors:
allowCredentials: [{
id: ****,
type: 'public-key',
transports: [
'internal',
'hybrid'
]
}, {
id: ****,
type: 'public-key',
transports: [
'internal',
'hybrid'
]
}, ...]
};
const credential = await navigator.credentials.get({
publicKey: publicKeyCredentialRequestOptions,
signal: abortController.signal
});
// This does not run until the user selects a passkey.
const credential = {};
credential.id = cred.id;
credential.rawId = cred.id; // Pass a Base64URL encoded ID string.
credential.type = cred.type;
// ...
}
PublicKeyCredentialDescriptor 객체는 다음으로 구성됩니다.
id: RP가 패스키 등록 시 가져온 공개 키 사용자 인증 정보의 ID입니다.type: 이 필드는 일반적으로'public-key'입니다.transports: 이 사용자 인증 정보를 보유한 기기에서 지원하는 전송에 관한 힌트입니다. 브라우저에서 사용자에게 외부 기기를 제시하도록 요청하는 UI를 최적화하는 데 사용됩니다. 이 목록이 제공되는 경우 각 사용자 인증 정보를 등록하는 동안getTransports()를 호출한 결과가 포함되어야 합니다.
요약
검색 가능한 사용자 인증 정보는 사용자 이름 입력을 건너뛸 수 있도록 하여 패스키 로그인 환경을 훨씬 더 사용자 친화적으로 만듭니다. residentKey, requireResidentKey, allowCredentials를 조합하면 RP는 다음과 같은 로그인 환경을 구현할 수 있습니다.
- 모달 계정 선택기를 표시합니다.
- 패스키 양식 자동 완성을 표시합니다.
- 재인증
검색 가능한 사용자 인증 정보를 현명하게 사용하세요. 이렇게 하면 사용자가 원활하게 이용하고 참여할 가능성이 높은 정교한 패스키 로그인 환경을 설계할 수 있습니다.