Face ID and Touch ID feel like strong security, and they can be, but only if you use them the right way. The common mistake is treating biometric authentication as a yes-or-no check: ask the system "is this the right user," get back true, and open the feature. That boolean is a UI gate, not a cryptographic guarantee, and on a compromised device it can be defeated. The secure pattern binds biometrics to the Keychain, so a secret is released by the Secure Enclave only after a successful biometric check. Here is how iOS biometrics work and how to use them so they actually protect something.
Short answer
On iOS, biometric authentication uses the LocalAuthentication framework to verify the user with Face ID or Touch ID. Per Apple's documentation, the secure way to use it is not to trust a simple success boolean from a policy evaluation, which is only a UI gate, but to bind the biometric check to the Keychain using access control, so a protected secret is released by the Secure Enclave only after a successful authentication. Biometrics gate local access to something; they do not replace server-side authentication. Add the NSFaceIDUsageDescription string, protect secrets with biometric-gated Keychain access control, and keep your server session and tokens as the real authority.
What you should know
- Biometrics verify the user locally: Face ID or Touch ID via LocalAuthentication.
- A success boolean is not security: it is a UI gate that can be bypassed.
- Bind to the Keychain: protect a secret so it releases only after biometrics.
- The Secure Enclave enforces it: hardware-backed, not a value your code trusts.
- It does not replace server auth: it gates local access, not the backend.
How does biometric authentication work on iOS?
Through the LocalAuthentication framework, which checks the user with Face ID or Touch ID. Your app creates an authentication context and asks the system to evaluate a policy, biometrics, or biometrics with a device-passcode fallback, and the system runs the prompt and returns whether authentication succeeded. You also add an NSFaceIDUsageDescription string so iOS can explain why your app uses Face ID. This is straightforward, and that is part of the problem: the easy path is to evaluate the policy, get a success result, and then proceed in your own code, which works but leans entirely on trusting that returned boolean. How much that protects depends on what you do with the result, not on the prompt appearing.
What is the trap with a success boolean?
That a boolean your code checks can be bypassed on a compromised device. The table contrasts the approaches.
| Approach | What protects the secret |
|---|---|
| Evaluate policy, trust the success boolean | Your code's check; bypassable if the runtime is compromised |
| Bind biometrics to a Keychain item via access control | The Secure Enclave releases the secret only on success |
| No binding, secret available regardless | Nothing; the gate is cosmetic |
If your app simply asks for biometric success and then reads a secret it already holds, an attacker who can manipulate the runtime, on a jailbroken device, for instance, can make the check return success or skip it, since the secret was never actually tied to the authentication. The stronger design stores the secret in the Keychain with biometric access control, so the item is only decrypted and released by the Secure Enclave after a genuine biometric match. Then the authentication is enforced by hardware, not by a branch in your code that can be patched.
How do you use biometrics securely?
Bind the biometric check to the Keychain, and keep the server as the authority. Store the sensitive value, a token, a key, a credential, in the Keychain with an access control that requires biometric authentication, so retrieving it forces a successful Face ID or Touch ID check enforced by the Secure Enclave, rather than your code deciding based on a boolean. Choose the access control level deliberately, for example requiring the current enrolled biometrics so that adding a new fingerprint or face invalidates access. Treat biometrics as gating local access to something on the device, while your backend still authenticates the session with proper tokens, since a local biometric success says nothing to your server by itself. And add the usage-description string so Face ID is permitted. The principle is that the secret, not a boolean, should depend on the authentication.
What to watch out for
The first trap is trusting the policy-evaluation success result as if it were security, when it is a UI gate; bind sensitive data to the Keychain instead. The second is treating a local biometric success as backend authentication, when your server still needs its own session and tokens. The third is omitting NSFaceIDUsageDescription, which prevents Face ID use and can cause a rejection. A pre-submission scan such as PTKD.com (https://ptkd.com) reads the compiled IPA against OWASP MASVS and assesses how your app stores secrets and uses the Keychain, which complements reviewing whether your biometric gate actually protects a secret. The access-control design you implement in the app.
What to take away
- iOS biometrics use LocalAuthentication for Face ID and Touch ID, but a success boolean from a policy evaluation is a UI gate, not security.
- The secure pattern binds the biometric check to a Keychain item via access control, so the Secure Enclave releases the secret only after a genuine match.
- Biometrics gate local access; they do not replace server-side authentication, which still needs proper tokens and sessions.
- Add NSFaceIDUsageDescription, protect secrets with biometric-gated Keychain access, and use a pre-submission scan such as PTKD.com to check how your app stores secrets.

