Warunkowe tworzenie klucza dostępu (promowanie po zalogowaniu)

Z tego przewodnika dowiesz się, jak automatycznie i w tle zarejestrować klucz dostępu użytkownika natychmiast po udanym zalogowaniu się za pomocą hasła, co pozwoli zminimalizować problemy i zwiększyć liczbę użytkowników kluczy dostępu.

Odpowiedni moment na aktywację

Automatyczne tworzenie kluczy dostępu (znane też jako tworzenie warunkowe lub cicha promocja po zalogowaniu) MUSI być uruchamiane natychmiast po udanym, pełnym zalogowaniu się przy użyciu hasła.

  • Nie próbuj tworzyć warunkowo w przypadku procesów bez hasła (np. magicznych linków, haseł jednorazowych SMS czy federacji tożsamości).
  • Jeśli wymagane jest uwierzytelnianie wielopoziomowe, przed rozpoczęciem tworzenia warunkowego MUSISZ poczekać, aż wszystkie czynniki zostaną pomyślnie zweryfikowane.
  • Przed wysłaniem żądań do punktów końcowych tworzenia upewnij się, że aktywna jest prawidłowa, uwierzytelniona sesja użytkownika.

Etapy wdrażania

1. Przerwij wcześniejsze działania autouzupełniania

Jeśli strona logowania korzysta z autouzupełniania formularzy (warunkowy interfejs użytkownika / Get), aktywne wywołanie pobierania danych logowania musi zostać przerwane, aby zapobiec konfliktom w przeglądarce.

  • Przed wywołaniem navigator.credentials.create() wywołaj abortController.abort() w obiekcie AbortController dołączonym do oczekującego żądania autouzupełniania navigator.credentials.get().

2. Wykrywanie funkcji

Sprawdź, czy warunkowe tworzenie jest dostępne, sprawdzając conditionalCreate za pomocą PublicKeyCredential.getClientCapabilities().

const capabilities = await PublicKeyCredential.getClientCapabilities();
if (capabilities.conditionalCreate) {
  // Conditional create is available
}

3. Tworzenie klucza dostępu za pomocą funkcji warunkowego tworzenia

  • Przekaż mediation: 'conditional' w opcjach navigator.credentials.create(). Sygnalizuje to przeglądarce, że proces tworzenia klucza dostępu ma być obsługiwany dyskretnie w tle lub kontekstowo, bez wyświetlania uciążliwych modalnych okien dialogowych.
  • Wypełnij pole excludeCredentials identyfikatorami istniejących danych logowania klucza dostępu użytkownika, aby uniknąć rejestrowania zduplikowanych kluczy.

4. Cicha obsługa błędów

  • Umieść prompt tworzenia klucza dostępu (navigator.credentials.create) w bloku try/catch. MUSISZ przechwytywać i ignorować typowe wyjątki dla użytkownika (InvalidStateError, NotAllowedError, AbortError) bez wyświetlania mu interfejsu błędu.

5. Weryfikacja obecności użytkownika po stronie serwera

  • Punkt końcowy weryfikacji po stronie serwera MUSI złagodzić wymaganie dotyczące obecności użytkownika (requireUserPresence: false) TYLKO podczas weryfikacji danych logowania wygenerowanych przez aktywator warunkowego tworzenia. W przypadku standardowych treści o charakterze jednoznacznie seksualnym rygorystyczna weryfikacja obecności musi pozostać aktywna.

6. Obsługa nieudanej weryfikacji serwera

  • Jeśli metoda navigator.credentials.create() zakończy się powodzeniem, ale pobieranie weryfikacji serwera zwróci nieprawidłową odpowiedź (np. nie powiedzie się weryfikacja podpisu), wywołaj metodę PublicKeyCredential.signalUnknownCredential(), aby zapobiec pozostawaniu osieroconych danych logowania u dostawcy kluczy dostępu.

Przykładowy kod

// optionsFetch and registerVerifyFetch are app-defined server endpoint requests
import { optionsFetch, registerVerifyFetch } from './api.js';

async function triggerConditionalCreate(loginAbortController) {
  const capabilities = await PublicKeyCredential.getClientCapabilities();
  if (capabilities.conditionalCreate !== true) {
    return; // Platform does not support conditional creation
  }

  // 1. Abort any active autofill conditional-get controllers to clear the WebAuthn pipeline
  loginAbortController.abort();

  // 2. Fetch creation options signaling the backend that this is a conditional request
  const creationOptionsJSON = await optionsFetch({ conditional: true });
  const publicKey = PublicKeyCredential.parseCreationOptionsFromJSON(creationOptionsJSON);

  let credential;
  try {
    // 3. Invoke silent credentials creation prompt
    credential = await navigator.credentials.create({ 
      publicKey,
      mediation: 'conditional' // Silent background creation mediation
    });
  } catch (e) {
    // 4. Silently swallow common WebAuthn browser exceptions
    if (['InvalidStateError', 'NotAllowedError', 'AbortError'].includes(e.name)) {
      return; 
    }
    console.error('Unexpected conditional create error:', e);
    return;
  }

  // 5. Server verification step using dedicated Try/Catch block
  let encodedResponse = credential.toJSON();
  try {
    const response = await registerVerifyFetch(encodedResponse);
    if (!response.ok) {
      // If the server verification fails, clean up using Signal API
      if (PublicKeyCredential.signalUnknownCredential) {
        await PublicKeyCredential.signalUnknownCredential({
          rpId, // RP ID must match the one defined on the server
          credentialId: encodedResponse.id
        });
      }
    }
  } catch (serverErr) {
    console.error('Verification network failure:', serverErr);
    if (PublicKeyCredential.signalUnknownCredential) {
      await PublicKeyCredential.signalUnknownCredential({
        rpId, // RP ID must match the one defined on the server
        credentialId: encodedResponse.id
      });
    }
  }
}

Strategie zastępcze

Zastępcze wykrywanie funkcji klucza dostępu

Zawsze instaluj „webauthn-polyfills” i importuj je w kontekście. Pamiętaj, że jeśli obsługiwany jest format PublicKeyCredential, obsługiwany jest też format PublicKeyCredential.getClientCapabilities.

import 'webauthn-polyfills';

Zastępcza synchronizacja interfejsu Signal API

Interfejs WebAuthn Signal API (webauthn-signals) to progresywna optymalizacja, która służy do synchronizowania menedżerów haseł ze stanem danych logowania na serwerze.

  • Fallback Experience: Gated via if (PublicKeyCredential.signalUnknownCredential). Jeśli nie jest obsługiwana, synchronizacja weryfikacji w tle jest pomijana bez zgłaszania wyjątków przeglądarki.

Łatwa serializacja JSON – kreacja zastępcza

Zawsze instaluj „webauthn-polyfills” i importuj je w kontekście. Jeśli obsługiwany jest format PublicKeyCredential, obsługiwane są też formaty PublicKeyCredential.parseCreationOptionsFromJSON i PublicKeyCredential.prototype.toJSON.

import 'webauthn-polyfills';