Szczegółowe dane logowania dostępne do znalezienia

Chociaż dane logowania FIDO, takie jak klucze dostępu, mają zastąpić hasła, w większości przypadków mogą też zwolnić użytkownika z konieczności wpisywania nazwy użytkownika. Umożliwia to użytkownikom uwierzytelnianie przez wybranie konta z listy kluczy dostępu, które mają w przypadku bieżącej witryny.

Starsze wersje kluczy bezpieczeństwa były zaprojektowane jako metody uwierzytelniania dwuetapowego i wymagały identyfikatorów potencjalnych danych logowania, a tym samym wpisania nazwy użytkownika. Dane logowania, które klucz bezpieczeństwa może znaleźć bez znajomości ich identyfikatorów, nazywane są danymi logowania, które można wykryć. Większość danych logowania FIDO tworzonych obecnie to dane logowania, 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 zostaną utworzone jako klucze dostępu (dane logowania, które można wykryć), podczas tworzenia danych logowania określ residentKeyrequireResidentKey.

Podmioty ufające mogą używać wykrywalnych danych logowania, pomijając parametr 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, zidentyfikowanych przez właściwość user.name ustawioną w momencie tworzenia. Jeśli użytkownik wybierze jedną z nich, user.idwartość zostanie uwzględniona w wynikowym podpisie. Serwer może wtedy użyć tego identyfikatora lub zwróconego identyfikatora danych logowania, aby wyszukać konto zamiast wpisanej nazwy użytkownika.

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

requireResidentKeyresidentKey

Aby utworzyć klucz dostępu, określ authenticatorSelection.residentKeyauthenticatorSelection.requireResidentKeynavigator.credentials.create() z wartościami wskazanymi poniżej.

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ć wykrywalne dane logowania. Jeśli nie można go utworzyć, zwracana jest wartość NotSupportedError.
  • 'preferred': RP woli utworzyć wykrywalne dane logowania, ale akceptuje też dane logowania niewykrywalne.
  • 'discouraged': RP woli utworzyć dane logowania, których nie można wykryć, ale akceptuje dane logowania, które można wykryć.

requireResidentKey:

  • Ta właściwość jest zachowywana ze względu na zgodność wsteczną ze starszą wersją specyfikacji WebAuthn Level 1. Ustaw tę wartość na true, jeśli residentKey ma wartość 'required', w przeciwnym razie ustaw ją na false.

allowCredentials

RP mogą używać allowCredentials na navigator.credentials.get(), aby kontrolować proces uwierzytelniania za pomocą klucza dostępu. Zwykle są 3 rodzaje uwierzytelniania za pomocą klucza dostępu:

Dzięki wykrywalnym danym logowania strony RP mogą wyświetlać modalny selektor kont, w którym użytkownik może wybrać konto, na które chce się zalogować, a następnie przejść weryfikację. Jest to odpowiednie w przypadku procesu uwierzytelniania za pomocą klucza dostępu zainicjowanego przez naciśnięcie przycisku przeznaczonego do uwierzytelniania za pomocą klucza dostępu.

Aby zapewnić taką obsługę, pomiń parametr allowCredentials lub przekaż do niego pustą tablicę w 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;
  
  // ...
}

Wyświetlanie autouzupełniania formularza klucza dostępu

Opisany powyżej selektor kont w oknie modalnym sprawdza się, gdy większość użytkowników korzysta z kluczy dostępu i ma je dostępne na urządzeniu lokalnym. Użytkownikom, którzy nie mają lokalnych kluczy dostępu, nadal będzie się wyświetlać okno modalne z prośbą o użycie klucza dostępu z innego urządzenia. Podczas przechodzenia na klucze dostępu możesz chcieć uniknąć wyświetlania tego interfejsu użytkownikom, którzy nie skonfigurowali klucza dostępu.

Zamiast tego wybór klucza dostępu może być uwzględniany w podpowiedziach autouzupełniania w polach tradycyjnego formularza logowania, obok zapisanych nazw użytkowników i haseł. Dzięki temu użytkownik z kluczami dostępu może „wypełnić” formularz logowania, wybierając swój klucz dostępu, użytkownicy z zapisanymi parami nazwy użytkownika i hasła mogą je wybrać, a użytkownicy, którzy nie mają żadnej z tych opcji, mogą wpisać nazwę użytkownika i hasło.

Jest to idealne rozwiązanie, gdy dostawca tożsamości przechodzi migrację i używa zarówno haseł, jak i kluczy dostępu.

Aby zapewnić taką wygodę użytkownikom, oprócz przekazania pustej tablicy do właściwości allowCredentials lub pominięcia parametru określ mediation: 'conditional'navigator.credentials.get() i dodaj do pola do wprowadzania danych HTML username adnotację autocomplete="username webauthn" lub do pola do wprowadzania danych password adnotację autocomplete="password webauthn".

Wywołanie funkcji navigator.credentials.get() nie spowoduje wyświetlenia żadnego interfejsu, ale jeśli użytkownik skupi się na polu do wprowadzania danych z adnotacjami, 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, a dopiero potem obietnica zwrócona przez .get() zostanie rozwiązana z wynikiem. Jeśli użytkownik nie wybierze klucza dostępu, obietnica nigdy nie zostanie spełniona.

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 tworzeniu takiego interfejsu znajdziesz w artykule Logowanie za pomocą klucza dostępu przez automatyczne wypełnianie formularza oraz w ćwiczeniu z programowania Implementowanie kluczy dostępu za pomocą automatycznego wypełniania formularza w aplikacji internetowej.

Ponowne uwierzytelnianie

W niektórych przypadkach, np. podczas ponownego uwierzytelniania za pomocą kluczy dostępu, identyfikator użytkownika jest już znany. W tym przypadku chcemy użyć klucza dostępu bez wyświetlania przez przeglądarkę lub system operacyjny selektora kont. Możesz to zrobić, przekazując listę identyfikatorów danych logowania w parametrze allowCredentials.

W takim przypadku, jeśli któreś z wymienionych danych logowania są dostępne lokalnie, użytkownik od razu zostanie poproszony o odblokowanie urządzenia. Jeśli nie, użytkownik zostanie poproszony o użycie innego urządzenia (telefonu lub klucza bezpieczeństwa) z prawidłowym identyfikatorem.

Aby zapewnić taką wygodę, podaj listę identyfikatorów danych logowania użytkownika. RP powinien mieć możliwość wysyłania zapytań do tych interfejsów, ponieważ użytkownik jest już znany. Podaj identyfikatory danych logowania jako obiekty PublicKeyCredentialDescriptor we właściwości allowCredentials w 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 danych logowania za pomocą klucza publicznego, który RP uzyskał podczas rejestracji klucza dostępu.
  • type: to pole ma zwykle wartość 'public-key'.
  • transports: wskazówka dotycząca transportów obsługiwanych przez urządzenie, na którym znajdują się te dane logowania. Przeglądarki używają jej do optymalizacji interfejsu, który prosi użytkownika o przedstawienie urządzenia zewnętrznego. Jeśli ta lista jest podana, powinna zawierać wynik wywołania funkcji getTransports() podczas rejestracji każdego poświadczenia.

Podsumowanie

Wykrywalne dane logowania znacznie ułatwiają logowanie się za pomocą klucza dostępu, ponieważ użytkownicy nie muszą wpisywać nazwy użytkownika. Dzięki połączeniu residentKey, requireResidentKeyallowCredentials dostawcy usług mogą zapewnić logowanie, które:

  • Wyświetl selektor kont w formie okna modalnego.
  • Wyświetl autouzupełnianie formularza klucza dostępu.
  • Ponowne uwierzytelnianie.

Rozważnie korzystaj z danych logowania, które można wykryć. Dzięki temu możesz projektować zaawansowane logowanie za pomocą klucza dostępu, które będzie wygodne dla użytkowników i z którego będą chętniej korzystać.