How to Implement Touch ID and Face ID Authentication in iOS

Integrate Touch ID and Face ID in iOS using the LAContext class from the LocalAuthentication framework.

Understanding the Local Authentication Framework

The LocalAuthentication framework provides biometric and device passcode authentication. It centers on LAContext, which offers two essential methods. canEvaluatePolicy(_:error:) checks whether authentication is possible on the device. evaluatePolicy(_:localizedReason:reply:) performs the actual authentication.

Two authentication policies are available:

  • .deviceOwnerAuthenticationWithBiometrics - authenticates with Touch ID or Face ID only. No passcode fallback.
  • .deviceOwnerAuthentication - tries biometry first, then falls back to the device passcode automatically.

Step 1: Import and Check Biometric Availability

Import the framework and verify the device supports biometry:

import LocalAuthentication

func authenticateWithBiometrics() {
    let context = LAContext()
    let reason = "Sign in to your account"
    var error: NSError?

    guard context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &error) else {
        if let error = error {
            print(error.localizedDescription)
        }
        showPasswordLogin()
        return
    }
}

canEvaluatePolicy returns false when the device lacks biometry hardware, the user has not enrolled fingerprints or face, or the device passcode is not set. Always provide a password fallback in these cases.

Step 2: Perform Biometric Authentication

Call evaluatePolicy after confirming biometry is available:

context.evaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, localizedReason: reason) { success, error in
    if success {
        DispatchQueue.main.async {
            self.performSegue(withIdentifier: "showHome", sender: nil)
        }
    } else {
        DispatchQueue.main.async {
            self.handleAuthenticationError(error)
        }
    }
}

The completion handler runs on a background thread. Dispatch all UI updates to the main queue using DispatchQueue.main.async.

Step 3: Handle Authentication Errors

The LAError enum covers common failure scenarios:

func handleAuthenticationError(_ error: Error?) {
    guard let laError = error as? LAError else { return }

    switch laError.code {
    case .authenticationFailed:
        showPasswordLogin()
    case .userCancel:
        break
    case .userFallback:
        showPasswordLogin()
    case .systemCancel:
        showPasswordLogin()
    case .passcodeNotSet:
        showPasswordLogin()
    case .biometryNotEnrolled:
        showPasswordLogin()
    case .biometryNotAvailable:
        showPasswordLogin()
    default:
        showPasswordLogin()
    }
}

For .userCancel, do nothing. The user intentionally stopped the process. For .userFallback, present the password screen since the user tapped Enter Password. For all other errors, show the password login as a fallback.

Step 4: Add Face ID Usage Description to Info.plist

Face ID requires a usage description in Info.plist. Add the key Privacy - Face ID Usage Description with a string explaining why your app needs biometric access. Example: "Authentication is required to access your account."

Without this entry, evaluatePolicy fails on Face ID devices with an LAError.biometryNotAvailable error.

Using deviceOwnerAuthentication for Seamless Fallback

Use .deviceOwnerAuthentication instead of .deviceOwnerAuthenticationWithBiometrics for automatic passcode fallback:

context.evaluatePolicy(.deviceOwnerAuthentication, localizedReason: reason) { success, error in

This policy presents biometry first. If biometry fails, is unavailable, or the user cancels, the system shows the device passcode screen automatically. You do not need to implement a separate password interface.

Testing Touch ID and Face ID

Test on a physical device with Touch ID or Face ID configured. The authentication dialog appears automatically. Face ID authenticates silently when the user looks at the device.

Test in the iOS Simulator using the Features menu:

  • Features > Face ID > Enrolled enables Face ID for the simulator session
  • Features > Face ID > Matching Face simulates successful authentication
  • Features > Face ID > Non-matching Face simulates failed authentication
  • Features > Touch ID > Enrolled enables Touch ID
  • Features > Touch ID > Matching Touch simulates success
  • Features > Touch ID > Non-matching Touch simulates failure

Best Practices for Biometric Authentication

Always provide a password or passcode fallback. Not every user has biometrics configured. Some users prefer passwords. A fallback ensures every user can access the app.

Use deviceOwnerAuthentication for broader compatibility. This policy handles passcode fallback automatically, reducing code complexity and providing a seamless user experience.

Keep the localizedReason text clear and specific. "Sign in to your account" or "Authorize purchase" tells users why authentication is required. Generic text reduces trust.

Test every error path. Biometric authentication can fail from hardware issues, enrollment changes, system interruptions, and user actions. Handle each case appropriately.

Store sensitive data in the Keychain, not in UserDefaults. Local Authentication verifies identity but does not store data. Use SecAccessControl with biometric protection for Keychain items:

let access = SecAccessControlCreateWithFlags(nil,
    kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly,
    .biometryCurrentSet,
    nil)

Respect user preferences. If a user cancels biometric authentication repeatedly, offer a Don't Ask Again option. Store this preference and skip biometric prompts on subsequent launches.

Summary

This tutorial covered the complete implementation process from setup to working code. You now have a functional implementation that you can extend and customize for your own projects. The same patterns apply to related features in the iOS ecosystem.

Frequently Asked Questions

Can I test this on the iOS Simulator? Some features require a physical device with a compatible processor. The article notes specific sections where the Simulator is sufficient and where a real device is required.

What is LAContext? LAContext is the class in Apple's LocalAuthentication framework that checks whether biometrics are available and asks the user to authenticate with Touch ID, Face ID or their passcode.

What are the prerequisites for this tutorial? You need Xcode installed on a Mac and basic familiarity with Swift programming. No prior experience with the specific framework is required.

All articles