패스키와 같은 FIDO 사용자 인증 정보는 비밀번호를 대체하는 것을 목표로 하지만 대부분 사용자가 사용자 이름을 입력하지 않아도 됩니다. 이를 통해 사용자는 현재 웹사이트에 있는 패스키 목록에서 계정을 선택하여 인증할 수 있습니다.
이전 버전의 보안 키는 2단계 인증 방법으로 설계되었으며 잠재적 사용자 인증 정보의 ID가 필요했으므로 사용자 이름을 입력해야 했습니다. 보안 키가 ID를 몰라도 찾을 수 있는 사용자 인증 정보를 검색 가능한 사용자 인증 정보라고 합니다. 오늘날 생성되는 대부분의 FIDO 사용자 인증 정보는 검색 가능한 사용자 인증 정보입니다. 특히 비밀번호 관리자나 최신 보안 키에 저장된 패스키가 그렇습니다.
사용자 인증 정보가 패스키 (검색 가능한 사용자 인증 정보)로 생성되도록 하려면 사용자 인증 정보가 생성될 때 residentKey 및 requireResidentKey를 지정하세요.
신뢰 당사자 (RP)는 패스키 인증 중에 allowCredentials를 생략하여 검색 가능한 사용자 인증 정보를 사용할 수 있습니다. 이 경우 브라우저 또는 시스템은 생성 시 설정된 user.name 속성으로 식별되는 사용 가능한 패스키 목록을 사용자에게 표시합니다. 사용자가 하나를 선택하면 user.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="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는 다음과 같은 로그인 환경을 달성할 수 있습니다.
- 모달 계정 선택기를 표시합니다.
- 패스키 양식 자동 완성을 표시합니다.
- 재인증
검색 가능한 사용자 인증 정보를 현명하게 사용하세요. 이렇게 하면 사용자가 원활하게 느끼고 참여할 가능성이 높은 정교한 패스키 로그인 환경을 설계할 수 있습니다.