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 podania 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 podaj wartości residentKeyrequireResidentKey.

Strony uzależnione (RP) mogą używać możliwych do znalezienia danych uwierzytelniających, pomijając allowCredentials podczas uwierzytelniania za pomocą klucza dostępu. W takich przypadkach przeglądarka lub system wyświetla 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, w systemie navigator.credentials.create() wpisz wartości authenticatorSelection.residentKey i authenticatorSelection.requireResidentKey za pomocą podanych niżej 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 preferuje tworzenie danych logowania możliwych do znalezienia, ale akceptuje dane logowania niemożliwe do znalezienia.
  • 'discouraged': preferuje tworzenie danych logowania niemożliwych do znalezienia, ale akceptuje takie dane logowania.

requireResidentKey:

  • Ta właściwość jest zachowana na potrzeby zgodności wstecznej z WebAuthn Level 1, starszą wersją specyfikacji. Ustaw tę wartość na true, jeśli residentKey ma wartość 'required'. W przeciwnym razie ustaw ją na false.

allowCredentials

Usługodawcy mogą używać allowCredentials w usłudze navigator.credentials.get(), aby kontrolować uwierzytelnianie za pomocą klucza. Istnieją zwykle 3 rodzaje uwierzytelniania za pomocą kluczy 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 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ć taki efekt, 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 z kluczem 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 pojawi się okno modalne, w którym użytkownik będzie mógł przedstawić klucz 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 zostać uwzględniony w autouzupełnianiu pól w tradycyjnym formularzu logowania razem z zapisanymi nazwami użytkowników i hasłami. 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 bez tych danych mogą wpisać swoją nazwę użytkownika i hasło.

Takie rozwiązanie jest idealne, gdy RP przechodzi proces migracji z mieszanym użyciem haseł 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 nie zostanie zrealizowana.

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 tym przypadku chcemy użyć klucza dostępu, bez opcji wyboru konta w przeglądarce lub systemie operacyjnym. Aby to zrobić, przekaż 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 otrzyma prośbę o odblokowanie urządzenia. W przeciwnym razie użytkownik zobaczy prośbę o przedstawienie innego urządzenia (telefonu lub klucza bezpieczeństwa) z ważnymi danymi logowania.

Aby to umożliwić, podaj listę identyfikatorów danych logowania dla logującego się użytkownika. RP powinny móc przesłać do nich zapytanie, 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 zwykle zawiera wartość 'public-key'.
  • transports: wskazówka dotycząca transportu obsługiwanego przez urządzenie z tymi danymi uwierzytelniającymi, używana przez przeglądarki do optymalizacji interfejsu użytkownika, w którym 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 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ększać ich zaangażowanie.