암호에 대한 사용 사례
이 항목에서는 암호 키에 대한 몇 가지 사용 사례에 대해 설명합니다.
사용 사례 1: 부트스트래핑
웹에서 계정을 부트스트래핑합니다.
1.1: 사용자 인증
이 섹션은 RP(신뢰 당사자)가 클라이언트 디바이스를 제어하는 사용자를 아직 모르는 경우에 적용됩니다. RP에서 사용할 수 있는 브라우저 아티팩트(예: 로컬 스토리지의 쿠키 또는 자격 증명 ID)는 없지만 지금은 사용자에게 RP가 있는 기존 계정이 있다고 가정합니다.
계정을 부트스트랩하려면 사용자에게 로그인 페이지를 제공합니다.
먼저 사용자에게 계정 식별자를 요청합니다. 일반적으로 사용자 이름 또는 전자 메일 주소입니다.
암호에 대한 자동 채우기 UI를 지원하려면 다음을 확인합니다.
- 사용자 이름 입력 필드의
username
기존 자동 완성 주석에 값 및webauthn
값을 추가합니다.
<div>
<label for="username">Username:</label>
<input name="username" id="loginform.username"
autocomplete="username webauthn">
</div>
- 페이지 로드 시 문을 사용하여
if
자동 채우기 UI(조건부 조정)를 사용할 수 있는지 확인한 다음, 다음을mediation: "conditional"
사용하여 호출navigator.credentials.get()
합니다userVerification: "preferred"
.
<script>
(async () => {
if (
typeof window.PublicKeyCredential !== 'undefined'
&& typeof window.PublicKeyCredential.isConditionalMediationAvailable === 'function'
) {
const available = await PublicKeyCredential.isConditionalMediationAvailable();
if (available) {
try {
// Retrieve authentication options for `navigator.credentials.get()`
// from your server.
const authOptions = await getAuthenticationOptions();
// This call to `navigator.credentials.get()` is "set and forget."
// The Promise will resolve only if the user successfully interacts
// with the browser's autofill UI to select a passkey.
const webAuthnResponse = await navigator.credentials.get({
mediation: "conditional",
publicKey: {
...authOptions,
// See note about userVerification below.
userVerification: "preferred",
}
});
// Send the response to your server for verification, and
// authenticate the user if the response is valid.
await verifyAutoFillResponse(webAuthnResponse);
} catch (err) {
console.error('Error with conditional UI:', err);
}
}
}
})();
</script>
위의 경우 다음과 같은 일이 발생합니다.
- 서버에서 인증 옵션을 검색합니다. 최소한 임
challenge
의로 반환하고rpId
이 인증 요청과 연결됩니다. - 사용자가 사용자 이름 필드와 상호 작용할 때 브라우저와 플랫폼은 신뢰 당사자와 함께 사용할 수 있는 암호가 플랫폼 인증자에 있는지 여부를 확인합니다.
- 이 경우 암호를 선택할 수 있는 옵션으로 사용자에게 표시됩니다(브라우저의 암호 관리자에 저장된 사용자 이름과 같이 자동으로 채울 수 있는 다른 자격 증명과 함께). 브라우저/플랫폼은 아래 표시된 것과 유사한 UI를 렌더링할 수 있습니다. 그러나 정확한 모양과 느낌은 플랫폼 또는 폼 팩터마다 다릅니다.
- 사용자가 암호를 선택하는 경우 플랫폼 UI는 (종종 생체 인식 기반) 사용자 확인 검사를 통해 사용자를 안내합니다.
- 사용자가 사용자 확인을 성공적으로 통과하면 호출이
navigator.credentials.get()
성공하고 WebAuthn 응답을 반환합니다. - 사용자가 암호 이외의 자격 증명을 선택하는 경우 브라우저/플랫폼은 다른 적절한 작업(예: 사용자 이름 자동 채우기)을 선택하고 호출이
navigator.credentials.get()
확인되지 않습니다. - 사용자가 "다른 디바이스에서 Passkey" 옵션을 선택하는 경우(정확한 텍스트는 플랫폼에 따라 약간 다를 수 있음) 브라우저/플랫폼은 FIDO2 보안 키 또는 CDA(디바이스 간 인증) 흐름을 사용하여 스마트폰 또는 태블릿의 암호를 사용하여 통화에 WebAuthn 응답을 전달하도록
navigator.credentials.get()
사용자를 안내합니다. - 확인 및 추가 보안 검사를 위해 WebAuthn 응답을 서버에 보냅니다. 모든 검사가 성공하면 이 사용자에 대해 인증된 세션을 시작합니다.
이것이 WebAuthn의 조건부 UI(또는 더 일반적으로 자동 채우기 UI) 모드라고 하는 이유입니다. 사용자가 확인을 통해 또는 휴대폰을 사용하여 사용자를 안내하는 플랫폼 인증자 UI는 사용자가 이 디바이스에 암호를 가지고 있거나 "다른 디바이스" 옵션을 선택하는 경우에만 표시됩니다.
여기서 볼 수 있듯이 이 모드에서는 호출이 navigator.credentials.get()
성공하거나 확인되지 않기 때문에 호출이 성공하지 않습니다. 성공하면 호출 결과에 사용자 ID와 서명된 WebAuthn 어설션이 모두 표시됩니다. 이 어설션은 RP(신뢰 당사자)가 사용자를 인증하는 데 사용합니다.
호출이 성공하지 못하면 레거시 사용자 인증을 수행해야 합니다. 이 첫 번째 페이지에서 사용자 이름을 가져온 다음, 후속 페이지에서 사용자에게 적절한 추가 로그인 챌린지(예: 암호, SMS 챌린지에 응답 등)를 제공합니다. 사용자가 암호를 잊어버렸거나 일반 로그인 챌린지를 통과할 수 없는 경우 계정 복구 단계가 포함될 수 있습니다. 사용자가 모든 로그인 챌린지를 통과하면 인증되고 로그인된 것으로 간주됩니다.
사용자에게 RP(신뢰 당사자)가 있는 계정이 없는 경우 일반적으로 사용자에게 로그인 페이지에서 계정을 만드는 옵션을 제공합니다. 사용자가 해당 옵션을 선택하는 경우 새 계정을 여는 데 필요한 정보를 수집합니다. 새 계정을 성공적으로 열면 인증되고 로그인된 것으로 간주됩니다.
사용자가 로그인한 후에는 새 암호를 설정해야 할 수 있습니다. 다음 경우 중 한 가지 작업을 수행합니다.
- 사용자가 암호 사용과 같이 암호가 아닌 로그인 챌린지를 전달하여 디바이스에서 계정을 부트스트래핑했습니다.
- 사용자가 RP(신뢰 당사자)에서 새 계정을 만들었으므로 로그인된 것으로 간주됩니다.
- 사용자가 암호를 사용하고 있었지만, 위 예제에 표시된 "다른 디바이스"를 선택하여 현재 사용 중인 디바이스와 다른 디바이스를 사용했습니다. 반환된 PublicKeyCredential 개체에서 authenticatorAttachment 특성을 검사하여 확인할 수 있습니다.
1.2: 디바이스 간 인증
사용자가 다른 장치(예: 휴대폰, 태블릿 또는 FIDO2 보안 키)에서 암호를 사용한 경우 인증 응답(getAssertion)의 authenticatorAttachment 속성 값이 cross-platform
포함됩니다.
이 시나리오에서는 사용자에게 로컬 디바이스에 암호를 만들 수 있는 옵션을 제공합니다. 사용자가 다른 디바이스를 사용할 필요가 없으므로 나중에 더 원활한 사용자 환경이 생성됩니다.
1.3: 사용자 확인에 대한 참고 사항
이 지침은 userVerification을 설정하며preferred
, 이는 가능한 경우 사용자 확인이 시도됨을 의미합니다.
데스크톱 컴퓨터 및 이전 노트북과 같은 일부 장치에는 생체 인식 센서가 없을 수 있습니다. 이러한 디바이스에서 userVerification이 설정된 required
경우 사용자에게 암호를 사용하여 로그인할 때마다 시스템 로그인 암호를 입력하라는 메시지가 표시될 수 있습니다. 그리고 그것은 그들에게 실망 스러울 수 있습니다.
사용되는 경우 preferred
일부 플랫폼 인증자는 디바이스에 생체 인식 센서가 있는 경우 항상 사용자 확인 검사가 필요하지만 디바이스가 없는 디바이스에서 사용자 확인을 건너뛸 수 있습니다.
사용자 확인 결과(인증자 데이터 플래그로 전달됨)는 실제 사용자 확인 결과를 반영하며 항상 서버의 요구 사항에 따라 유효성을 검사해야 합니다.
1.4: 사용자를 암호로 선택
먼저 다단계 인증을 비롯한 다른 로그인 방법을 사용하여 사용자가 충분히 강력하게 인증되었는지 확인합니다.
둘째, 사용자의 디바이스 및 OS(운영 체제) 콤보가 다음을 호출하여 암호를 지원하는지 확인합니다.
PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable()
암호 키가 지원되면 해당 암호가 반환 true
됩니다. 지원되지 않으면 반환 false
되며 암호 등록 흐름을 중단해야 합니다.
암호를 만들도록 제공하는 사용자에게 옵트인 또는 "업셀" 모달/중간 또는 페이지를 제공합니다.
팁
사용자가 완전히 정보에 입각한 동의를 제공하려면 현재 디바이스의 잠금을 해제할 수 있는 모든 사용자가 신뢰 당사자(RP)의 계정에 액세스할 수 있음을 설명하는 더 긴 설명을 표시(또는 연결)하는 것이 좋습니다.
사용자가 동의하면 아래 예제에 표시된 옵션을 사용하여 호출 navigator.credentials.create()
합니다.
navigator.credentials.create({
publicKey: {
rp: {
// User-friendly name of your service.
name: "Passkeys Developer",
// Relying party (RP) identifier (hostname/FQDN).
id: passkeys.contoso"
},
user: {
// Persistent, unique identifier for the user account in your backend.
id: Uint8Array.from("0525bc79-5a63-4e47-b7d1-597e25f5caba", c => c.charCodeAt(0)),
// User-friendly identifier often displayed to the user (for example, email address).
name: "amanda@contoso.com",
// Human-readable display name, sometimes displayed by the client.
displayName: "Amanda Brady"
},
// The challenge is a buffer of cryptographically random bytes generated on your backend,
// and should be tightly bound to the current user session.
challenge: Uint8Array.from("XZJscsUqtBH7ZB90t2g0EbZTZYlbSRK6lq7zlN2lJKuoYMnp7Qo2OLzD7xawL3s", c => c.charCodeAt(0)),
pubKeyCredParams: [
// An array of objects describing what public key types are acceptable to a server.
{
"type": "public-key",
"alg": -7 // EC P256
},
{
"type": "public-key",
"alg": -257 // RSA
}
],
excludeCredentials: [
// Array of credential IDs for existing passkeys tied to the user account.
// This avoids creating a new passkey in an authenticator that already has
// a passkey tied to the user account.
{
// Example only.
type: "public-key",
id: new Uint8Array([21, 31, 56, ...]).buffer
},
{
// Example only.
type: "public-key",
id: new Uint8Array([21, 31, 56, ...]).buffer
}
],
authenticatorSelection: {
// Tells the authenticator to create a passkey.
residentKey: "required",
// Tells the client/authenticator to request user verification where possible;
// for example, a biometric or a device PIN.
userVerification: "preferred"
},
"extensions": {
// Returns details about the passkey.
"credProps": true
}
}
})
참고 항목
대부분의 RP(신뢰 당사자)는 증명 컨베이어 매개 변수 attestation
를 지정하지 않거나(따라서 기본값은 없음으로) 값을 indirect
명시적으로 사용하는 것이 좋습니다. 이는 가장 간소화된 사용자 환경을 보장합니다(플랫폼은 다른 유형의 증명 전달에 대한 사용자 동의를 얻을 가능성이 높으며, 이로 인해 사용자가 생성을 취소하여 실패한 자격 증명 생성의 일부가 더 클 수 있습니다).
WebAuthn 호출이 해결되면 서버에 응답을 보내고 반환된 공개 키 및 자격 증명 ID를 이전에 인증된 사용자 계정과 연결합니다.
사용 사례 2: 재인증
다음 이유 중 어떤 이유로든 재인증에 암호를 사용해야 할 수 있습니다.
- 사용자가 로그아웃했고 이제 다시 로그인하려고 합니다.
- 사용자 세션이 비활성으로 인해 만료되었으며 사용자가 다시 로그인하려고 합니다.
- 사용자가 중요한 작업을 수행하려고 하며 사용자 세션에 대한 제어를 다시 확인해야 합니다.
이러한 각 상황에서 사용자를 다시 인증하려면 이전 사용 사례에서 설정한 암호를 사용합니다. WebAuthn API 호출은 세 가지 경우 모두 동일하지만 제공하는 UI 처리는 약간 다릅니다. 사용자가 특정 계정을 지정하므로 플랫폼에서는 사용자에게 서비스에서 다른 계정을 선택하라는 메시지를 표시하지 않습니다.
2.1: 중요한 작업
세 번째 이유로 먼저 UI를 살펴보겠습니다. 중요한 작업을 다시 인증해야 하는 경우 사용자에 대해 하나 이상의 암호에 대한 자격 증명 ID가 있는지 확인합니다.
이러한 자격 증명 ID를 사용할 수 없는 경우 재인증에 적합한 기존 로그인 챌린지를 제공합니다. 예를 들면 다음과 같습니다.
팁
이 로그인 챌린지 페이지에서는 사용자가 계정 식별자를 변경할 수 없는 것이 좋습니다. 또한 로그인 챌린지는 디바이스의 권한이 없는 사용자가 통과할 수 없는 문제여야 합니다.
반면에 사용자에 대해 하나 이상의 암호 자격 증명 ID를 찾을 경우 다시 인증에 암호를 사용할 수 있습니다.
사용자가 준비되면(위의 예제에서 "이동" 단추를 클릭할 때) 모든 사용자의 암호 자격 증명 ID를 전달하여 호출 navigator.credentials.get()
합니다.
navigator.credentials.get({
publicKey: {
challenge: ...,
rpId: ...,
allowCredentials: [{
type: "public-key",
id: new UInt8Array([21, 31, 56, ...]).buffer,
}, {
type: "public-key",
id: new UInt8Array([21, 31, 56, ...]).buffer,
}, {
...
}],
// see note below
userVerification: "preferred",
}
});
참고 항목
이전 사용 사례에서 userVerification에 대한 지침을 읽어야 합니다.
사용자가 대신 "다른 방법 시도"를 클릭하는 경우 다른 로그인 메서드(암호 등)를 제공하여 다시 인증해야 합니다(사용자가 사용할 수 있는 다른 로그인 메서드가 있다고 가정).
2.2: 만료된 세션 및 로그아웃
이제 사용자가 로그아웃했거나 RP(신뢰 당사자)가 사용자의 세션이 만료되어 재인증이 트리거되는 경우를 살펴보겠습니다. 이를 용이하게 하기 위해 RP는 사용자가 로그아웃한 것을 고려할 때(쿠키 또는 로컬 스토리지와 같은 브라우저 아티팩트 사용 가능) 이전에 로그인한 계정을 상기시키는 일종의 사용자 세션 상태를 유지해야 합니다.
참고 항목
RP(신뢰 당사자)는 로그아웃을 포괄적인 작업으로 처리하여 사용자의 ID에 대한 모든 참조를 삭제하도록 선택할 수 있습니다. 이러한 RP는 후속 로그인을 계정 부트스트랩처럼 처리하고 앞에서 설명한 단계를 반복해야 합니다.
그러면 RP로 다음과 같이 로그인 페이지를 제공할 수 있습니다.
사용자가 "다른 계정 사용"을 클릭하면 이전 사용 사례에 대해 설명한 대로 계정 부트스트랩 흐름을 입력해야 합니다. 여기서 플랫폼은 사용자가 사용할 계정을 선택할 수 있도록 하는 단계를 반복합니다.
참고 항목
이 경우 사용자에게 제안된 계정이 로그인 페이지에 나열되지 않도록 완전히 제거할 수 있는 기능을 제공해야 합니다.
그러나 사용자가 "로그인" 단추를 클릭하면 사용자와 연결된 암호 자격 증명 ID가 하나 이상 있는지 확인합니다. 자격 증명 ID를 사용할 수 없는 경우 재인증에 적합한 기존 로그인 챌린지를 제공합니다. 예를 들면 다음과 같습니다.
반면에 사용자에 대해 하나 이상의 암호 자격 증명 ID를 찾을 경우 다시 인증에 암호를 사용할 수 있습니다.
사용자가 준비되면(위의 예제에서 "이동" 단추를 클릭할 때) navigator.credentials.get()
이미 표시된 대로 호출합니다(즉, 모든 사용자의 암호 자격 증명 ID를 전달함).
사용자가 대신 "다른 방법 시도"를 클릭하는 경우 다른 로그인 메서드(암호 등)를 제공하여 다시 인증해야 합니다(사용자가 사용할 수 있는 다른 로그인 메서드가 있다고 가정).
다음 단계
다음으로, 암호에 대한 도구 및 라이브러리를 참조 하세요.
추가 정보
Windows developer