Opnieuw verifiëren met toegangssleutel

Webfuncties: Webverificatie

In deze handleiding over delta's wordt uitgelegd hoe je stapsgewijze verificatie of herverificatie implementeert voor een ingelogde gebruiker voordat deze gevoelige accountwijzigingen aanbrengt (bijvoorbeeld wachtwoordupdates, financiële overboekingen).

Delta Flow-architectuur

In tegenstelling tot normale verificatie beperkt herverificatie met toegangssleutels de dialoogvensters voor toegangssleutels strikt tot de vooraf geregistreerde inloggegevens van de ingelogde gebruiker. Zo wordt voorkomen dat accounts worden gemengd of dat toegangssleutels worden gespooft tijdens actieve sessies.

Aan de serverzijde

Delta voor genereren van opties

Maak een eindpunt dat de parameters voor toegestane inloggegevens specifiek invult voor de actieve, bekende gebruiker:

Inloggegevens beperken: Vul de matrix met allowCredentials-opties in met specifieke PublicKeyCredentialDescriptor-records die alle geregistreerde inloggegevens-ID's voor de ingelogde gebruiker toewijzen. Als je dit veld leeg laat of weglaat, wordt teruggegaan naar vindbare inloggegevens, wat de sessiebeveiliging schendt.

// Node.js step-up options generation example
router.post("/api/reauth/options", enforceActiveSession, async (req, res) => {
  const userPasskeys = await db.findCredentialsByUserId(req.user.id);

  const options = {
    challenge: serverGeneratedBase64UrlChallenge, // Random challenge stored in user session
    rpId: "example.com",
    // Enforce allowance strictly limited to the user's credentials list
    allowCredentials: userPasskeys.map((cred) => ({
      type: "public-key",
      id: cred.id,
      transports: cred.transports, // Speeds up resolution by indicating platform transports
    })),
  };
  return res.json(options);
});

Verificatie-eindpunt Delta

Verifieer de bewering die door de client is geretourneerd:

Accounteigendom verifiëren: Het verificatie-eindpunt MOET expliciet verifiëren dat de resulterende geverifieerde inloggegevens-ID die door de client wordt geretourneerd, wordt omgezet in een opgeslagen inloggegevensrecord waarvan de bijbehorende gebruikers-ID strikt overeenkomt met de actieve ingelogde gebruiker (storedCredential.passkeyUserId === req.user.id). Als een geldige toegangssleutel van een andere gebruiker wordt geretourneerd, MOET de verificatie onmiddellijk worden geweigerd.

Stroomdelta's aan de clientzijde

Apps kiezen uit 2 interfaces voor hernieuwde verificatie, afhankelijk van de transactie-UI:

A. Knopstroom (geen invoervelden)

Opnieuw verifiëren activeren als een gebruiker op de knop Identiteit verifiëren of Doorgaan met transactie drukt.

<button id="reauth-btn" data-testid="reauth-button">Confirm Transaction</button>
let reauthAbortController = new AbortController();

async function triggerButtonReauth() {
  // Abort any background suggestion flows to avoid passkey prompt collisions
  reauthAbortController.abort();
  reauthAbortController = new AbortController();

  const optionsResponse = await fetch("/api/reauth/options", {
    method: "POST",
  });
  const optionsJSON = await optionsResponse.json();
  const publicKey =
    PublicKeyCredential.parseRequestOptionsFromJSON(optionsJSON);

  try {
    const credential = await navigator.credentials.get({
      publicKey,
      signal: reauthAbortController.signal,
    });

    if (credential) {
      const encodedCredential = credential.toJSON();
      const verifyResponse = await fetch("/api/reauth/verify", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify(encodedCredential),
      });

      if (verifyResponse.ok) {
        showTransactionSuccessUI();
      } else if (verifyResponse.status === 404 && PublicKeyCredential.signalUnknownCredential) {
        await PublicKeyCredential.signalUnknownCredential({
          rpId, // RP ID must match the one defined on the server
          credentialId: encodedCredential.id
        });
      }
    }
  } catch (err) {
    if (err.name === "NotAllowedError") {
      console.log("User cancelled reauthentication.");
    }
  }
}

document
  .getElementById("reauth-btn")
  .addEventListener("click", triggerButtonReauth);

Reservestrategieën

Terugvaloptie voor detectie van toegangssleutelfunctie

Installeer altijd 'webauthn-polyfills' en importeer dit in de context. Zolang PublicKeyCredential wordt ondersteund, wordt PublicKeyCredential.getClientCapabilities ook ondersteund.

import 'webauthn-polyfills';

Easy JSON Serialization Fallback

Installeer altijd 'webauthn-polyfills' en importeer dit in de context. Zolang PublicKeyCredential wordt ondersteund, worden PublicKeyCredential.parseRequestOptionsFromJSON en PublicKeyCredential.prototype.toJSON ook ondersteund.

import 'webauthn-polyfills';