Szczegółowe dane logowania dostępne do znalezienia

Dane logowania FIDO, takie jak klucze dostępu, mają zastąpić hasła, ale większość z nich może też uwolnić użytkownika od konieczności wpisywania nazwy użytkownika. Umożliwia to użytkownikom uwierzytelnianie się przez wybranie konta z listy kluczy dostępu do bieżącej witryny.

Wcześniejsze wersje kluczy bezpieczeństwa były zaprojektowane jako metody uwierzytelniania dwuetapowego i wymagały identyfikatorów potencjalnych danych uwierzytelniających, co wymagało wpisania nazwy użytkownika. Dane uwierzytelniające, które klucz bezpieczeństwa może znaleźć bez znajomości ich identyfikatorów, nazywamy danymi uwierzytelniania możliwymi do odkrycia. Większość danych uwierzytelniających FIDO tworzonych obecnie to dane uwierzytelniające, które można wykryć, zwłaszcza klucze dostępu przechowywane w menedżerze haseł lub na nowoczesnym kluczu bezpieczeństwa.

Aby mieć pewność, że dane logowania są tworzone jako klucze dostępu (dane logowania, które można wykryć), podczas ich tworzenia określ wartości residentKeyrequireResidentKey.

Użytkownicy mogą używać danych logowania, które można wykryć, pomijając allowCredentials podczas uwierzytelniania za pomocą klucza dostępu. W takich przypadkach przeglądarka lub system wyświetlają użytkownikowi listę dostępnych kluczy dostępu z uwzględnieniem właściwości user.name ustawionej podczas tworzenia. Jeśli użytkownik wybierze jedną z nich, wartość user.id zostanie uwzględniona w podpisanym dokumencie. Serwer może użyć tego identyfikatora lub zwróconego identyfikatora danych logowania, aby wyszukać konto zamiast wpisanej nazwy użytkownika.

Interfejsy selektora kont, takie jak omówione wcześniej, nigdy nie wyświetlają niewykrywalnych danych logowania.

requireResidentKeyresidentKey

Aby utworzyć klucz dostępu, ustaw authenticatorSelection.residentKeyauthenticatorSelection.requireResidentKey na navigator.credentials.create(), przypisując im odpowiednie wartości.

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': musisz utworzyć dane logowania, które są możliwe do znalezienia. Jeśli nie można go utworzyć, zwracana jest wartość NotSupportedError.
  • 'preferred': RP woli utworzyć dane logowania możliwe do znalezienia, ale akceptuje dane logowania niemożliwe do znalezienia.
  • 'discouraged': RP woli utworzyć niewykrywalne dane logowania, ale akceptuje dane logowania możliwe do znalezienia.

requireResidentKey:

  • Ta właściwość jest zachowana ze względu na zgodność z poziomem 1 specyfikacji WebAuthn, czyli starszą wersją specyfikacji. Ustaw tę wartość na true, jeśli residentKey to 'required'. W przeciwnym razie ustaw ją na false.

allowCredentials

Reprezentanci mogą używać allowCredentialsnavigator.credentials.get(), aby kontrolować uwierzytelnianie za pomocą klucza. Zwykle występują 3 typy uwierzytelniania za pomocą klucza dostępu:

Dzięki możliwości wyświetlania danych logowania dostawcy usług mogą wyświetlić użytkownikowi okno wyboru konta, w którym może on wybrać konto, na którym chce się zalogować, a następnie przejść weryfikację. Jest to odpowiednie rozwiązanie w przypadku procesu uwierzytelniania za pomocą klucza dostępu inicjowanego przez naciśnięcie przycisku przeznaczonego do uwierzytelniania za pomocą klucza dostępu.

Aby uzyskać takie działanie, pomiń parametr allowCredentials lub przekaż mu pusty tablic w funkcji navigator.credentials.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 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;
  
  // ...
}

Pokaż autouzupełnianie formularza klucza dostępu

Opisywany powyżej modalny selektor kont działa dobrze, jeśli większość użytkowników używa kluczy dostępu i ma je dostępne na urządzeniu lokalnym. W przypadku użytkownika, który nie ma lokalnych kluczy dostępu, nadal pojawia się okno modalne z prośbą o podanie klucza dostępu z innego urządzenia. Podczas przenoszenia użytkowników na klucze dostępu możesz unikać tego interfejsu w przypadku użytkowników, którzy nie skonfigurowali jeszcze kluczy.

Zamiast tego wybór klucza dostępu może być uwzględniony w prośbach autouzupełniania w polach tradycyjnego formularza logowania, obok zapisanych nazw użytkowników i haseł. Dzięki temu użytkownik z kluczem dostępu może „wypełnić” formularz logowania, wybierając klucz dostępu, użytkownicy z zapisanymi nazwami użytkowników i hasłami mogą wybrać te dane, a użytkownicy, którzy nie mają tych danych, mogą wpisać swoją nazwę użytkownika i hasło.

Takie rozwiązanie jest idealne, gdy RP przechodzi proces migracji, używając zarówno haseł, jak i kluczy dostępu.

Aby uzyskać takie działanie, oprócz przekazania pustego tablicy do właściwości allowCredentials lub pominięcia parametru, określ mediation: 'conditional' w przypadku navigator.credentials.get() i opatrz pole wejściowe HTML username atrybutem autocomplete="username webauthn" lub pole wejściowe password atrybutem autocomplete="password webauthn".

Wywołanie navigator.credentials.get() nie spowoduje wyświetlenia żadnego interfejsu użytkownika, ale jeśli użytkownik skoncentruje się na opatrzonym adnotacją polu wprowadzania danych, dostępne klucze dostępu zostaną uwzględnione w opcjach autouzupełniania. Jeśli użytkownik wybierze jedną z nich, przejdzie standardową weryfikację odblokowania urządzenia. Dopiero wtedy obietnica zwrócona przez .get() zostanie zrealizowana. Jeśli użytkownik nie wybierze klucza dostępu, obietnica nigdy się nie spełni.

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" ...>

Więcej informacji o tym, jak tworzyć takie rozwiązania, znajdziesz w ćwiczeniach Logowanie się za pomocą klucza dostępu przez autouzupełnianie formularzy oraz w ćwiczeniu z programowania Wdrażanie kluczy dostępu z autouzupełnianiem formularzy w aplikacji internetowej.

Ponowne uwierzytelnianie

W niektórych przypadkach, np. gdy do ponownego uwierzytelnienia używane są klucze dostępu, identyfikator użytkownika jest już znany. W takim przypadku chcielibyśmy użyć klucza dostępu bez wyświetlania w przeglądarce lub systemie operacyjnym jakiejkolwiek formy selektora konta. Aby to zrobić, prześlij listę identyfikatorów danych logowania w parametrze allowCredentials.

W takim przypadku, jeśli na urządzeniu są dostępne jakiekolwiek nazwane dane logowania, użytkownik od razu zobaczy prośbę o odblokowanie urządzenia. W przeciwnym razie użytkownik zostanie poproszony o przedstawienie innego urządzenia (telefonu lub klucza bezpieczeństwa) z prawidłowymi danymi logowania.

Aby to umożliwić, podaj listę identyfikatorów danych logowania dla logującego się użytkownika. RP powinien mieć możliwość wysłania zapytania, ponieważ użytkownik jest już znany. Podaj identyfikatory danych logowania jako obiekty PublicKeyCredentialDescriptor w przypadku właściwości allowCredentials w elementach navigator.credentials.get().

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;
  
  // ...
}

Obiekt PublicKeyCredentialDescriptor składa się z:

  • id: identyfikator poświadczeń klucza publicznego uzyskanych przez RP podczas rejestracji klucza dostępu.
  • type: to pole jest zwykle 'public-key'.
  • transports: wskazówka dotycząca transportu obsługiwanego przez urządzenie zawierające te dane logowania. Jest ona używana przez przeglądarki do optymalizacji interfejsu, który prosi użytkownika o przedstawienie urządzenia zewnętrznego. Ta lista, jeśli zostanie podana, powinna zawierać wynik wywołania funkcji getTransports() podczas rejestracji każdego zestawu danych.

Podsumowanie

Dane logowania, które można znaleźć, znacznie ułatwiają logowanie się za pomocą klucza dostępu, ponieważ pozwalają pominąć wpisywanie nazwy użytkownika. Dzięki połączeniu funkcji residentKey, requireResidentKeyallowCredentials partnerzy reklamowi mogą korzystać z logowania, które:

  • Pokaż okno modalne z selektorem konta.
  • Wyświetlanie autouzupełniania formularza klucza dostępu.
  • Ponowne uwierzytelnianie.

Rozważnie używaj danych logowania, które są dostępne dla innych. Dzięki temu możesz zaprojektować zaawansowane funkcje logowania za pomocą klucza dostępu, które będą wygodne dla użytkowników i zwiększą ich zaangażowanie.