ASVS 5.0 V6.5.7 says biometric authentication may only be used as a secondary factor, together with either something the user has or something the user knows. A fingerprint or face check alone must not sign anyone in. It is a Level 3 requirement.
Why it matters
Biometrics are not secret, since faces and fingerprints are exposed daily, and they cannot be changed after a compromise. They are best as a local unlock for a protected key, not as the credential.
How to implement it
Use the platform pattern where the biometric unlocks a device bound key, and the server verifies a signature from that key.
- On mobile and in browsers, use WebAuthn or platform keystores. The biometric releases the private key. The server never sees biometric data.
- Combine with a password, PIN or enrolled device as the primary factor.
- Do not accept a raw biometric template or match result sent from a client.
const credential = await navigator.credentials.get({
publicKey: {
challenge: serverChallenge,
userVerification: "required", // biometric or PIN unlocks the key
allowCredentials: registeredIds,
},
});
// send credential to server, which verifies the signature against the stored public key
How to test it
- Try to log in with only a biometric prompt and no other factor. It must fail.
- Check the server code for any endpoint that accepts a client side match flag.
- Confirm no biometric templates are stored in your database.
Common mistakes
- Treating "biometric passed" from the client as proof.
- Offering biometric only login as a convenience.
Quick check
Is WebAuthn with biometric unlock a violation?
No. The key on the device is something the user has, and the biometric only unlocks it locally.