Поделиться через


Варианты использования для секретных ключей

В этом разделе описываются некоторые варианты использования ключей доступа.

Вариант использования 1. Начальная загрузка

Загрузка учетной записи в Интернете.

1.1. Проверка подлинности пользователя

Этот раздел применяется, когда проверяющая сторона (RP) еще не знает, кто управляет клиентским устройством. Артефакт браузера недоступен для RP (например, файла cookie или идентификатора учетных данных в локальном хранилище), хотя в настоящее время предполагается, что у пользователя есть существующая учетная запись с RP.

Чтобы загрузить учетную запись, обслуживают пользователя страницу входа.

Начните с запроса пользователя об идентификаторе учетной записи; Обычно имя пользователя или адрес электронной почты.

Вход

Чтобы поддерживать пользовательский интерфейс автозаполнения для секретных ключей, обязательно выполните следующие действия.

  1. username Добавьте и webauthn значение в любые существующие заметки автозавершения в поле ввода имени пользователя.
<div>
  <label for="username">Username:</label>
  <input name="username" id="loginform.username"
         autocomplete="username webauthn">
</div>
  1. На загрузке страницы используйте инструкциюif, чтобы проверить доступность пользовательского интерфейса автозаполнения (условного посредника), а затем вызвать navigator.credentials.get() с mediation: "conditional" ним.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 связанную с этим запросом проверки подлинности.
  • Когда пользователь взаимодействует с полем имени пользователя , браузер и платформа будут проверять, существует ли секретный ключ (в аутентификаторе платформы), который можно использовать с проверяющей стороной.
  • Если это так, то пароль будет представлен пользователю в качестве варианта выбора (наряду с другими учетными данными, которые могут быть автоматически заполнены, например имена пользователей, хранящиеся в диспетчере паролей браузера). Браузер или платформа могут отобразить пользовательский интерфейс, аналогичный приведенному ниже. Хотя точный вид и чувство зависит от одной платформы или форм-фактора к другой:

Вход с помощью секретного ключа

  • Если пользователь выбирает секретный ключ, пользовательский интерфейс платформы будет направлять пользователя с помощью проверки проверки подлинности пользователя (часто биометрических данных).
  • Если пользователь успешно прошел проверку пользователя, navigator.credentials.get() вызов завершается успешно и возвращает ответ WebAuthn.
  • Если пользователь выбирает учетные данные, отличные от ключа доступа, браузер или платформа выбирает другое соответствующее действие (например, автоматическое заполнение имени пользователя), а navigator.credentials.get() вызов не разрешается.
  • Если пользователь выбирает параметр "Passkey из другого устройства" (точный текст будет немного отличаться по платформе), браузер или платформа будет направлять пользователя с помощью ключа безопасности FIDO2 или потока проверки подлинности между устройствами (CDA) для использования секретного ключа со своего смартфона или планшета для доставки ответа WebAuthn на navigator.credentials.get() звонок.
  • Отправьте ответ WebAuthn на сервер для проверки и дополнительных проверок безопасности. Если все проверки выполнены успешно, начните сеанс, прошедший проверку подлинности для этого пользователя.

Именно поэтому этот интерфейс называется условным пользовательским интерфейсом (или, чаще всего, режимом автоматического заполнения) WebAuthn — пользовательским интерфейсом проверки подлинности платформы, который направляет пользователя через проверку или с помощью телефона, отображается только в том случае, если пользователь имеет секретный ключ на этом устройстве (или выбирает параметр другого устройства).

Как видно, в этом режиме navigator.credentials.get() вызов либо завершается успешно, либо он не выполняется, так как он никогда не разрешается. Если это произойдет успешно, результат вызова покажет идентификатор пользователя и подписанное утверждение WebAuthn, которое проверяющая сторона (RP) будет использоваться для проверки подлинности пользователя.

Если вызов не выполнен, необходимо выполнить устаревшую проверку подлинности пользователя. Вы получите имя пользователя с этой первой страницы, а на последующих страницах вы будете обслуживать соответствующие дополнительные задачи входа (например, пароли, реагирование на sms-вызовы и т. д.) пользователю. Они могут включать действия по восстановлению учетной записи в случае, если пользователь забыл свой пароль или иначе не сможет передать обычные проблемы входа. После того как пользователь прошел все проблемы входа, они считаются прошедшими проверку подлинности и вошли в систему.

Если у пользователя еще нет учетной записи с проверяющей стороной (RP), обычно пользователь сможет создать учетную запись на странице входа. Если пользователь выбирает этот параметр, вы собираете необходимые сведения от них, чтобы открыть новую учетную запись. Если они успешно открывают новую учетную запись, они также считаются прошедшими проверку подлинности и вошли в систему.

После входа пользователя может потребоваться настроить новый секретный ключ для них. Сделайте это для любого из следующих случаев:

  • Пользователь загрузил свою учетную запись на устройстве путем передачи проблем входа без секретного ключа (например, с помощью пароля).
  • Пользователь только что создал новую учетную запись на проверяющей стороне (RP), и он считается вошедшего из-за этого.
  • Пользователь использовал секретный ключ, но использовал другое устройство, отличное от используемого в данный момент (выбрав "другое устройство", показанное в приведенном выше примере). Это можно подтвердить, проверив атрибут authenticatorAttachment в возвращенном объекте PublicKeyCredential .

1.2. Межустройство

Если пользователь использовал ключ доступа с другого устройства (например, телефон, планшет или ключ безопасности FIDO2), то свойство authenticatorAttachment в ответе проверки подлинности (getAssertion) будет иметь значение cross-platform.

В этом сценарии предложите пользователю возможность создать секретный ключ на локальном устройстве. Это приведет к более простому пользовательскому интерфейсу в будущем, так как пользователь не потребуется использовать другое устройство.

Настройте секретный ключ на этом устройстве!

1.3. Примечание о проверке пользователей

Это руководство задает значение userVerificationpreferred, что означает, что проверка пользователя будет предпринята, когда это возможно.

Некоторые устройства, такие как настольные компьютеры и старые ноутбуки, могут не иметь биометрических датчиков. Если на этих устройствах задано requiredзначение userVerification, то пользователю может потребоваться ввести пароль для входа в систему с помощью секретного ключа. И это может быть разочаровано для них.

При preferred использовании некоторые средства проверки подлинности платформы всегда требуют проверки подлинности пользователя, если устройство имеет биометрические датчики, но может пропустить проверку пользователей на устройствах без них.

Результат проверки пользователя (переданный в флагах данных проверки подлинности) отражает фактический результат проверки пользователя и всегда должен проверяться на соответствие вашим требованиям на сервере.

1.4. Согласие пользователя на доступ к секретным ключам

Сначала убедитесь, что пользователь достаточно строго прошел проверку подлинности с помощью других методов входа, включая многофакторную проверку подлинности.

Во-вторых, убедитесь, что combo устройства пользователя и операционной системы (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
    }
  }
})

Примечание.

Рекомендуется, чтобы большинство проверяющих сторон (RPS) не указали параметр attestation передачи аттестации (таким образом, по умолчанию не указан), или вместо этого явно используйте это значение indirect. Это гарантирует наиболее упрощенное взаимодействие с пользователем (платформы, скорее всего, получают согласие от пользователя для других типов передач аттестации, что, скорее всего, приводит к большей части неудачных создания учетных данных из-за отмены создания учетных данных).

При разрешении вызова WebAuthn отправьте ответ на сервер и свяжите возвращенный открытый ключ и идентификатор учетных данных с ранее прошедшей проверку подлинности учетной записью пользователя.

Вариант использования 2. Повторная проверка подлинности

Использование секретных ключей для повторной проверки подлинности может потребоваться по любым из следующих причин:

  • Пользователь вошел в систему и теперь хочет войти снова.
  • Срок действия сеанса пользователя истек из-за неактивности, и пользователь хочет снова войти.
  • Пользователь должен выполнить конфиденциальное действие и повторно подтвердить контроль над сеансом пользователя.

Для повторной проверки подлинности пользователя в каждой из этих ситуаций вы будете использовать секретные ключи, настроенные в предыдущем случае использования. Вызов API WebAuthn одинаков во всех трех случаях, но предоставляемый пользовательский интерфейс немного отличается. Так как определенная учетная запись указана вами, платформа не предложит пользователю выбрать другую учетную запись в службе.

2.1. Конфиденциальные действия

Давайте рассмотрим пользовательский интерфейс по третьей причине , когда пришло время повторной проверки подлинности для конфиденциального действия, проверьте, есть ли идентификатор учетных данных по крайней мере один секретный ключ для пользователя.

Если такой идентификатор учетных данных недоступен, то для повторной проверки подлинности используется традиционная задача входа, например:

Давайте убедимся, что это вы 1

Совет

Рекомендуется, чтобы на этой странице вызова входа пользователи не могли изменить идентификатор учетной записи. Кроме того, проблема входа должна быть чем-то, что несанкционированный пользователь устройства не может пройти.

Если, с другой стороны, вы найдете по крайней мере один идентификатор учетных данных секретного ключа для пользователя, можно использовать ключи доступа для повторной проверки подлинности:

Давайте убедимся, что это вы 2

Когда пользователь готов (в приведенном выше примере при нажатии кнопки Go), вызовите 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 придется сохранить некоторое состояние сеанса пользователя, напоминающее им о учетной записи, которая ранее вошедла в систему, даже если они считают, что пользователь вышел из системы (это может быть достигнуто с помощью артефактов браузера, таких как файлы cookie или локальное хранилище).

Примечание.

Проверяющая сторона (RP) может рассматривать выход как комплексное действие и таким образом удалять все ссылки на удостоверение пользователя. Такой RP должен рассматривать последующий вход, как начальную загрузку учетной записи, и повторить описанные ранее действия.

Вы, как RP, можете затем служить страницей входа, как показано ниже:

С возвращением! 1

Если пользователь нажимает кнопку "Использовать другую учетную запись", необходимо ввести поток начальной загрузки учетной записи( как описано в предыдущем случае использования), повторив шаги там, где платформа позволит пользователю выбрать учетную запись, которую они хотят использовать.

Примечание.

В этом случае вы также должны предоставить пользователю возможность полностью удалить предлагаемую учетную запись из списка на странице входа.

Но если пользователь нажимает кнопку "Войти как", проверьте, есть ли у вас по крайней мере один идентификатор учетных данных секретного ключа, связанный с пользователем. Если идентификатор учетных данных недоступен, то выполните традиционную задачу входа, подходящую для повторной проверки подлинности, например:

С возвращением! 2

Если, с другой стороны, вы найдете по крайней мере один идентификатор учетных данных секретного ключа для пользователя, можно использовать ключи доступа для повторной проверки подлинности:

С возвращением! 3

Когда пользователь готов (в приведенном выше примере при нажатии кнопки "Перейти") вызов navigator.credentials.get(), точно так же, как показано (то есть путем передачи всех идентификаторов учетных данных доступа пользователя).

Если пользователь вместо этого нажимает кнопку "Попробовать еще один способ", вам следует предложить им другие методы входа (пароль и т. д.), чтобы повторно выполнить проверку подлинности (если у пользователя есть другие методы входа, доступные для них).

Следующие шаги

Далее см. статью "Инструменты и библиотеки" для ключей доступа.

Дополнительные сведения