Bird
Raised Fist0
iOS Swiftmobile~20 mins

Biometric authentication (Face ID, Touch ID) in iOS Swift - Mini App: Build & Ship

Choose your learning style10 modes available
Build: BiometricAuthScreen
This screen lets users authenticate using Face ID or Touch ID. It shows a button to start authentication and displays success or error messages.
Target UI
-------------------------
| Biometric Authentication |
|-------------------------|
|                         |
|   [ Authenticate ]       |
|                         |
| Status:                 |
|                         |
-------------------------
Add a button labeled 'Authenticate' centered on the screen.
When tapped, start biometric authentication using Face ID or Touch ID.
Show a status message below the button: 'Authentication succeeded' or 'Authentication failed' or error message.
Handle cases where biometrics are not available or not enrolled.
Use LocalAuthentication framework.
Starter Code
iOS Swift
import SwiftUI
import LocalAuthentication

struct BiometricAuthScreen: View {
    @State private var statusMessage = ""

    var body: some View {
        VStack(spacing: 20) {
            // TODO: Add Authenticate button here
            // TODO: Show statusMessage text here
        }
        .padding()
    }
}

struct BiometricAuthScreen_Previews: PreviewProvider {
    static var previews: some View {
        BiometricAuthScreen()
    }
}
Task 1
Task 2
Task 3
Task 4
Solution
iOS Swift
import SwiftUI
import LocalAuthentication

struct BiometricAuthScreen: View {
    @State private var statusMessage = ""

    var body: some View {
        VStack(spacing: 20) {
            Button("Authenticate") {
                authenticateUser()
            }
            .padding()
            .background(Color.blue)
            .foregroundColor(.white)
            .cornerRadius(8)

            Text(statusMessage)
                .foregroundColor(.gray)
                .multilineTextAlignment(.center)
                .padding(.horizontal)
        }
        .padding()
    }

    func authenticateUser() {
        let context = LAContext()
        var error: NSError?

        if context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &error) {
            let reason = "Please authenticate to continue."

            context.evaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, localizedReason: reason) { success, authenticationError in
                DispatchQueue.main.async {
                    if success {
                        statusMessage = "Authentication succeeded"
                    } else {
                        if let error = authenticationError {
                            statusMessage = error.localizedDescription
                        } else {
                            statusMessage = "Authentication failed"
                        }
                    }
                }
            }
        } else {
            DispatchQueue.main.async {
                if let error = error {
                    statusMessage = error.localizedDescription
                } else {
                    statusMessage = "Biometric authentication not available or not enrolled"
                }
            }
        }
    }
}

struct BiometricAuthScreen_Previews: PreviewProvider {
    static var previews: some View {
        BiometricAuthScreen()
    }
}

This solution uses SwiftUI to create a simple screen with a button labeled Authenticate. When the user taps the button, the authenticateUser() function runs.

Inside authenticateUser(), we create an LAContext object to check if biometric authentication is available and enrolled on the device.

If biometrics are available, we call evaluatePolicy to prompt the user for Face ID or Touch ID. The result is handled asynchronously, updating the statusMessage state to show success or failure.

If authentication fails, we show the error message if available, otherwise a generic failure message.

If biometrics are not available or not enrolled, we update the status message accordingly, showing the error description if available.

The UI updates automatically because statusMessage is a @State variable, and the text below the button shows the current status.

Final Result
Completed Screen
-------------------------
| Biometric Authentication |
|-------------------------|
|                         |
|   [ Authenticate ]       |
|                         |
| Status:                 |
| Authentication succeeded |
-------------------------
User taps 'Authenticate' button.
System shows Face ID or Touch ID prompt.
If user authenticates successfully, status changes to 'Authentication succeeded'.
If authentication fails or is canceled, status changes to 'Authentication failed' or shows error message.
If biometrics are unavailable, status shows 'Biometric authentication not available or not enrolled'.
Stretch Goal
Add a toggle to switch between Face ID and passcode fallback authentication.
💡 Hint
Use LAContext's deviceOwnerAuthentication policy to allow passcode fallback when biometrics fail or are unavailable.

Practice

(1/5)
1. What is the main purpose of using biometric authentication like Face ID or Touch ID in an iOS app?
easy
A. To change the app's theme automatically
B. To improve app loading speed
C. To securely verify the user's identity without typing a password
D. To send notifications to the user

Solution

  1. Step 1: Understand biometric authentication purpose

    Biometric authentication is designed to verify the user's identity securely using Face ID or Touch ID.
  2. Step 2: Compare options with purpose

    Only To securely verify the user's identity without typing a password describes secure identity verification without passwords, which is the main goal.
  3. Final Answer:

    To securely verify the user's identity without typing a password -> Option C
  4. Quick Check:

    Biometric authentication = Secure identity check [OK]
Hint: Biometrics replace passwords for secure login [OK]
Common Mistakes:
  • Thinking biometrics speed up app loading
  • Confusing biometric use with UI changes
  • Assuming biometrics send notifications
2. Which Swift code snippet correctly checks if biometric authentication is available before using it?
easy
A. let context = LAContext() if context.evaluatePolicy(.deviceOwnerAuthentication, error: nil) { // proceed }
B. let context = LAContext() var error: NSError? if context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &error) { // proceed }
C. let context = LAContext() if context.canEvaluatePolicy(.deviceOwnerAuthentication, error: nil) { // proceed }
D. let context = LAContext() if context.canAuthenticate() { // proceed }

Solution

  1. Step 1: Identify correct method to check biometric availability

    The method canEvaluatePolicy with .deviceOwnerAuthenticationWithBiometrics checks if biometrics are available.
  2. Step 2: Verify code syntax and usage

    let context = LAContext() var error: NSError? if context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &error) { // proceed } uses canEvaluatePolicy with correct policy and proper &error parameter, matching Apple's guidelines.
  3. Final Answer:

    let context = LAContext()\nvar error: NSError?\nif context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &error) {\n // proceed\n} -> Option B
  4. Quick Check:

    Check biometrics availability = canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics) [OK]
Hint: Use canEvaluatePolicy with biometric policy to check availability [OK]
Common Mistakes:
  • Using evaluatePolicy instead of canEvaluatePolicy for availability
  • Using wrong policy like .deviceOwnerAuthentication
  • Calling non-existent methods like canAuthenticate
3. Given this Swift code snippet, what will be printed if biometric authentication succeeds?
let context = LAContext()
context.evaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, localizedReason: "Access needed") { success, error in
  if success {
    print("Authentication succeeded")
  } else {
    print("Authentication failed")
  }
}
medium
A. Authentication succeeded
B. No output
C. Authentication failed
D. Syntax error

Solution

  1. Step 1: Understand evaluatePolicy callback behavior

    The closure receives a success boolean indicating if authentication passed.
  2. Step 2: Check the if condition for success

    If success is true, it prints "Authentication succeeded"; otherwise, it prints failure.
  3. Final Answer:

    Authentication succeeded -> Option A
  4. Quick Check:

    Success true prints "Authentication succeeded" [OK]
Hint: Success true means authentication passed and prints success message [OK]
Common Mistakes:
  • Confusing success and failure branches
  • Assuming no output from async closure
  • Thinking code has syntax errors
4. Identify the error in this Swift code for biometric authentication:
let context = LAContext()
var error: NSError?
if context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: error) {
  context.evaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, localizedReason: "Login") { success, error in
    if success {
      print("Access granted")
    }
  }
}
medium
A. The error parameter should be passed as &error to be mutable
B. evaluatePolicy should be called before canEvaluatePolicy
C. The localizedReason string is missing
D. LAContext must be declared as a class, not a let constant

Solution

  1. Step 1: Check error parameter usage in canEvaluatePolicy

    The error parameter must be passed as an inout pointer using &error to capture errors.
  2. Step 2: Verify other code parts

    evaluatePolicy is correctly called after canEvaluatePolicy, localizedReason is provided, and LAContext can be a let constant.
  3. Final Answer:

    The error parameter should be passed as &error to be mutable -> Option A
  4. Quick Check:

    Error param must be &error for canEvaluatePolicy [OK]
Hint: Pass error as &error to canEvaluatePolicy for error capture [OK]
Common Mistakes:
  • Passing error without & causing no error info
  • Calling evaluatePolicy before checking availability
  • Missing localizedReason string
  • Misunderstanding let vs var for LAContext
5. You want to allow users to authenticate using Face ID or Touch ID, but fallback to device passcode if biometrics fail or are unavailable. Which Swift code snippet correctly implements this behavior?
hard
A. let context = LAContext() var error: NSError? if context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &error) { context.evaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, localizedReason: "Authenticate") { success, error in if success { print("Biometric success") } else { print("Authentication failed") } } } else { print("Biometrics not available") }
B. let context = LAContext() context.evaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, localizedReason: "Authenticate") { success, error in if success { print("Authentication success") } else { print("Authentication failed") } }
C. let context = LAContext() if context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: nil) { context.evaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, localizedReason: "Authenticate") { success, error in if success { print("Biometric success") } else { context.evaluatePolicy(.deviceOwnerAuthentication, localizedReason: "Fallback") { success, error in if success { print("Passcode success") } else { print("Authentication failed") } } } } }
D. let context = LAContext() var error: NSError? if context.canEvaluatePolicy(.deviceOwnerAuthentication, error: &error) { context.evaluatePolicy(.deviceOwnerAuthentication, localizedReason: "Authenticate") { success, error in if success { print("Authentication success") } else { print("Authentication failed") } } }

Solution

  1. Step 1: Understand fallback requirement

    The app should try biometrics first, then fallback to device passcode if biometrics fail or are unavailable.
  2. Step 2: Analyze code options for fallback logic

    let context = LAContext() var error: NSError? if context.canEvaluatePolicy(.deviceOwnerAuthentication, error: &error) { context.evaluatePolicy(.deviceOwnerAuthentication, localizedReason: "Authenticate") { success, error in if success { print("Authentication success") } else { print("Authentication failed") } } } uses .deviceOwnerAuthentication policy which automatically prefers biometrics (Face ID/Touch ID) and falls back to passcode if unavailable or fails. It also properly checks availability first per Apple's guidelines.
  3. Final Answer:

    let context = LAContext()\nvar error: NSError?\nif context.canEvaluatePolicy(.deviceOwnerAuthentication, error: &error) {\n context.evaluatePolicy(.deviceOwnerAuthentication, localizedReason: \"Authenticate\") { success, error in\n if success {\n print(\"Authentication success\")\n } else {\n print(\"Authentication failed\")\n }\n }\n} -> Option D
  4. Quick Check:

    .deviceOwnerAuthentication policy = biometric fallback to passcode [OK]
Hint: Use .deviceOwnerAuthentication policy with canEvaluatePolicy check for fallback [OK]
Common Mistakes:
  • Using biometrics-only policy without fallback (Options A, B)
  • Direct evaluation without availability check
  • Syntax error with error: nil and incomplete fallback (Option D)
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard