검색 가능한 사용자 인증 정보 자세히 알아보기

패스키와 같은 FIDO 사용자 인증 정보는 비밀번호를 대체하는 것을 목표로 하지만 대부분의 경우 사용자는 사용자 이름을 입력하지 않아도 됩니다. 이렇게 하면 사용자가 현재 웹사이트에 대해 보유하고 있는 패스키 목록에서 계정을 선택하여 인증할 수 있습니다.

보안 키의 이전 버전은 2단계 인증 방식으로 설계되었으며, 잠재적인 크리덴셜의 ID를 요구했으므로 사용자 이름을 입력해야 합니다. 보안 키가 ID를 알지 못해도 찾을 수 있는 사용자 인증 정보를 검색 가능한 사용자 인증 정보라고 합니다. 오늘날 생성되는 대부분의 FIDO 사용자 인증 정보는 검색 가능한 사용자 인증 정보입니다. 특히 비밀번호 관리자나 최신 보안 키에 저장된 패스키가 여기에 해당합니다.

사용자 인증 정보를 패스키 (검색 가능한 사용자 인증 정보)로 만들려면 사용자 인증 정보를 만들 때 residentKeyrequireResidentKey를 지정합니다.

신뢰 당사자 (RP)는 다음을 생략하여 검색 가능한 사용자 인증 정보를 사용할 수 있습니다. 패스키 인증 중 allowCredentials 이 경우 브라우저 또는 시스템은 생성 시 설정된 user.name 속성으로 식별되는 사용 가능한 패스키 목록을 사용자에게 표시합니다. 사용자가 하나를 선택하면 user.id 값이 서명에 포함됩니다. 그런 다음 서버는 이를 사용하거나 반환된 사용자 인증 정보 ID를 사용하여 입력된 사용자 이름 대신 계정을 조회합니다.

앞에서 설명한 것처럼 계정 선택기 UI는 검색할 수 없는 사용자 인증 정보를 표시하지 않습니다.

requireResidentKeyresidentKey

패스키를 만들려면 navigator.credentials.create()에서 authenticatorSelection.residentKeyauthenticatorSelection.requireResidentKey를 다음과 같이 지정합니다.

<ph type="x-smartling-placeholder">
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 Level 1과의 하위 호환성을 위해 유지됩니다. residentKey'required'이면 true로 설정하고, 그렇지 않으면 false로 설정합니다.
를 통해 개인정보처리방침을 정의할 수 있습니다. <ph type="x-smartling-placeholder">

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는 다음과 같은 로그인 환경을 제공할 수 있습니다.

  • 모달 계정 선택기를 표시합니다.
  • 패스키 양식 자동 완성 표시
  • 재인증

검색 가능한 사용자 인증 정보를 현명하게 사용합니다. 이렇게 하면 사용자가 원활하게 이용하고 참여할 가능성이 높은 정교한 패스키 로그인 환경을 설계할 수 있습니다.