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';