Ana Sayfa / Blog / Face ID ve Touch ID: LocalAuthentication framework’ü doğru kullanmak

Face ID ve Touch ID: LocalAuthentication framework’ü doğru kullanmak

Biometric auth iOS'ta premium feature. LocalAuthentication API'si sade ama yanlış kullanımı kullanıcı güvenliğini riske atıyor. 5 uygulamadan pratik pattern'ler.

Biometric authentication iOS uygulamalarında çok temel bir feature oldu. Face ID ve Touch ID ile uygulamayı kilitlemek, hassas işlemleri onaylatmak, biometric-backed keychain kullanmak. Framework: LocalAuthentication.

5 uygulamamda biometric entegrasyonu yaptım. Bir bankacılık app’i, bir finans tracking’i, bir medical record app’i, iki privacy-sensitive productivity app’i. Her birinde biraz farklı pattern gerekti.

Temel API

import LocalAuthentication

let context = LAContext()
var error: NSError?

guard context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &error) else {
    print("Biometric not available: \(error?.localizedDescription ?? "")")
    return
}

context.evaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, localizedReason: "Uygulamaya erişmek için") { success, error in
    DispatchQueue.main.async {
        if success {
            // Auth success
        } else {
            // Auth failed
        }
    }
}

4 satır. Ama doğru kullanım detaylarda.

Policy seçimi

Iki ana policy:

.deviceOwnerAuthenticationWithBiometrics: sadece Face ID / Touch ID. Biometric başarısız olursa kullanıcı başka şey deneyemiyor.

.deviceOwnerAuthentication: biometric + fallback to passcode. Biometric başarısız olursa device passcode’u sorar.

Ben genelde .deviceOwnerAuthentication tercih ediyorum. Kullanıcı Face ID ile kabul edilmeyen bir durumda (maske, karanlık, güneş gözlüğü) passcode ile devam edebiliyor. Friction azalıyor.

İstisna: bazı finansal işlem confirmation’larında “only biometric” disipline uygun olabiliyor. Passcode somebody-else-knows risk.

localizedReason: kullanıcıya ne söylüyorsunuz

Face ID prompt’unda görünen metin. Spesifik ve aksiyon-odaklı olmalı.

Kötü: “Authentication”
İyi: “Finansal bilgilere erişmek için Face ID”

Kullanıcı “niye biometric istiyor?” sorusunu 1 saniyede cevaplayabilmeli. Belirsiz mesaj güvensizlik yaratıyor.

TR localizasyon:

context.evaluatePolicy(
    .deviceOwnerAuthenticationWithBiometrics,
    localizedReason: NSLocalizedString(
        "biometric.reason.vault",
        value: "Kasaya erişmek için",
        comment: ""
    )
) { ... }

Biometry type detection

Cihaz Face ID mı Touch ID mi var? Farklı metin göstermek için:

let context = LAContext()
var error: NSError?
context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &error)

switch context.biometryType {
case .faceID:
    buttonTitle = "Face ID ile gir"
case .touchID:
    buttonTitle = "Touch ID ile gir"
case .opticID:
    buttonTitle = "Optic ID ile gir" // Vision Pro
case .none:
    buttonTitle = "Şifre ile gir"
@unknown default:
    buttonTitle = "Güvenli giriş"
}

biometryType check’inden önce canEvaluatePolicy çağrılmalı, yoksa type .none döner.

Icon seçimi: SF Symbols faceid vs touchid kullanın. Kullanıcı ikonu görünce ne olacağını anlar.

Info.plist permission

iOS 11.3+ Face ID için permission gerekli. Info.plist:

<key>NSFaceIDUsageDescription</key>
<string>Uygulamanıza Face ID ile hızlı ve güvenli giriş yapabilirsiniz.</string>

Bu string yoksa Face ID prompt’u hiç çıkmıyor, app crash ediyor review’da. Touch ID için ayrı permission yok.

LAError handling

Evaluation sırasında çıkabilecek hata tipleri:

context.evaluatePolicy(...) { success, error in
    if let error = error as? LAError {
        switch error.code {
        case .userCancel:
            // Kullanıcı Cancel'a tıkladı, sessizce geç
        case .userFallback:
            // Kullanıcı "Şifre Kullan" dedi, passcode akışına yönlendir
        case .biometryNotAvailable:
            // Cihazda biometric yok veya kapalı
            showError("Face ID mevcut değil")
        case .biometryNotEnrolled:
            // Biometric var ama enroll edilmemiş
            showError("Face ID kurulu değil. Ayarlar'dan ekleyin.")
        case .biometryLockout:
            // 5 başarısız deneme, passcode gerekiyor
            showError("Face ID geçici olarak kilitli. Telefon şifresi gerekiyor.")
        case .passcodeNotSet:
            // Cihazda passcode yok
            showError("Telefon şifresi tanımlı değil.")
        case .systemCancel:
            // System call'ı iptal etti (incoming call, vs)
        case .invalidContext:
            // Context invalid
        default:
            showError("Kimlik doğrulanamadı.")
        }
    }
}

Her error type için farklı kullanıcı mesajı. Generic “auth failed” kullanıcıyı frustrate ediyor.

Biometric-backed Keychain

Biometric auth’un asıl gücü keychain’i biometric’le korumak. Kullanıcının password, token, secret key’i sadece biometric auth sonrası okunabilir oluyor.

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

let query: [String: Any] = [
    kSecClass as String: kSecClassGenericPassword,
    kSecAttrService as String: "com.example.vault",
    kSecAttrAccount as String: "user_token",
    kSecValueData as String: token.data(using: .utf8)!,
    kSecAttrAccessControl as String: access
]
SecItemAdd(query as CFDictionary, nil)

.biometryCurrentSet flag’i: “sadece şu anki biometric set ile eşleşen kullanıcı okuyabilir”. Kullanıcı Settings’ten yeni bir parmak veya yeni bir face ekler ise eski keychain item invalidate oluyor.

.biometryAny alternative: herhangi bir biometric eşleşmesi (mevcut veya sonradan eklenen). Security-sensitive app’ler için .biometryCurrentSet daha sıkı.

Retry policy

Biometric başarısız olunca ne yapmalı? Otomatik retry etmeyin. Kullanıcı butona tıklayıp tekrar denesin.

Biometric auth failed
 → "Tekrar dene" butonu göster
 → kullanıcı tıklayınca evaluatePolicy tekrar çağrılıyor

Automatic retry flashing Face ID dialog’u spam ediyor, kullanıcı agresif hissediyor.

App background’a girince

App background’a girince biometric lock’u yeniden gerektirmek isteyebilirsiniz. Yaygın pattern:

func applicationWillResignActive(_ application: UIApplication) {
    lockStartTime = Date()
}

func applicationDidBecomeActive(_ application: UIApplication) {
    if let startTime = lockStartTime,
       Date().timeIntervalSince(startTime) > 60 {
        // 60 saniyeden fazla background, lock gerekli
        showBiometricLock()
    }
    lockStartTime = nil
}

Kullanıcı başka app’e geçti 10 saniye sonra döndü ise lock açılması gereksiz. 60 saniye iyi eşik. Sensitive app’lerde 30 saniye, ultra-sensitive’lerde her background’da lock.

Two-factor: biometric + something

Biometric alone sufficient bazı durumlar için değil. Yüksek tutarlı işlemlerde ikinci faktör eklemek security best practice.

Pattern:
– Düşük risk: biometric yeterli
– Orta risk: biometric + PIN
– Yüksek risk: biometric + SMS OTP veya time-based OTP

Biometric replay attack’a karşı korumalı değil (fotoğraf ile Face ID atlatmak nadir ama mümkün). Yüksek işlemlerde sadece biometric’e güvenmeyin.

Test disiplini

Simulator’da Face ID simulate edilebiliyor (Features → Face ID → Matching Face/Non-matching Face). Touch ID de simulate ediliyor.

Bunlar hızlı development için iyi. Final test real device’da şart – edge case’ler (maskeli Face ID, parmak ıslak Touch ID) simulator’da emule edilmiyor.

Kullanıcı’ya opt-in imkan

Biometric zorunlu yapmak yerine opt-in sunmak daha iyi UX. İlk app açılışında “Her giriste Face ID sormamızı ister misiniz?” sorusu, yes ise keychain’e biometric-backed kaydetmek.

No diyen kullanıcı password-based normal akışı kullanıyor. Yes’in sadece opt-in olanlar için extra friction.

Performans

Face ID ~1 saniye, Touch ID ~0.5 saniye. Bu süre içinde app UI’ının hazır olması gerekiyor. Biometric prompt başarılıysa immediate geçiş, başarısızsa fallback UI.

App başladığında biometric prompt’u splash screen sırasında tetiklerseniz kullanıcı zaten bekliyor, tek beklenti oluyor. Ayrı bir lock screen’den sonra biometric prompt göstermek iki aşamalı bekleme yaratıyor.

Son tavsiye

Biometric auth güvenlik feature’ı ama aynı zamanda UX feature’ı. Doğru kullanıldığında kullanıcı memnun oluyor, yanlış kullanıldığında friction ekliyor.

Prensipler:
– Spesifik reason mesajı
– Error type’a göre kullanıcı mesajı
– Biometric-backed keychain ile hassas veri
– Background lock timing’i dengede
– Opt-in default
– Yüksek risk’te 2FA ile birleştir

Bu 6 prensip uygulanırsa biometric auth app’in güvenlik ve deneyim açısından premium tarafı oluyor.

Bu konuda bir projeniz mi var?

Kısa bir özet bırakın, 24 saat içinde size dönüş yapayım.

İletişime Geç