A production-ready, clean, and testable iOS Biometric Authentication SDK for Face ID and Touch ID.
- Features
- Requirements
- Installation
- Quick Start
- Configuration
- API Reference
- Best Practices
- Support
- License
- ๐ Face ID & Touch ID Support - Native iOS biometric authentication
- ๐ฑ iOS 12.0+ Compatible - Wide device support
- ๐ฏ Clean Public API - Simple, intuitive interface
- โ Protocol-Based Architecture - Fully testable with dependency injection
- ๐งต Thread-Safe - All operations safely dispatched to main thread
- ๐ Swift 6 Concurrency Ready - @Sendable closure support
- ๐ฆ Multiple Distribution - SPM, CocoaPods
- ๐ Semantic Error Types - Flexible error handling for UI
- ๐ก๏ธ Access Control - Internal classes protected from external access
- iOS: 12.0+
- Xcode: 14.0+
- Swift: 5.7+
- Dependencies: None
Add to your Package.swift:
dependencies: [
.package(url: "https://github.com/Definex-Mobile/iOS-BiometricAuth-SDK.git", from: "1.0.0")
]Or in Xcode:
- File โ Add Package Dependencies...
- Enter URL:
https://github.com/Definex-Mobile/iOS-BiometricAuth-SDK.git - Select version:
1.0.0or higher
Add to your Podfile:
pod 'DefXBiometric', :git => 'https://github.com/Definex-Mobile/iOS-BiometricAuth-SDK.git', :tag => '1.0.0'Then run:
pod installAdd Face ID usage description to your app's Info.plist:
<key>NSFaceIDUsageDescription</key>
<string>We need to verify your identity using Face ID</string>Important Notes:
NSFaceIDUsageDescriptionis required by Apple for Face IDNSCameraUsageDescriptionis NOT needed (biometric auth doesn't use camera)- Touch ID does not require usage description
- SDK cannot add this to Info.plist; host app must include it
import DefXBiometric// Check which biometric type is available
let biometricType = DefXBiometricAuth.shared.availableBiometricType()
switch biometricType {
case .faceID:
print("โ
Face ID is available")
case .touchID:
print("โ
Touch ID is available")
case .none:
print("โ No biometric authentication available")
}
// Check if biometric can be used right now
if DefXBiometricAuth.shared.isBiometricAvailable() {
print("โ
Biometric authentication is ready")
}DefXBiometricAuth.shared.authenticate(
reason: "Authenticate to access your account"
) { result in
switch result {
case .success:
print("โ
Authentication successful")
// Navigate to authenticated screen
case .failure(let error):
switch error {
case .cancelled:
// User cancelled - handle gracefully
break
case .notAvailable, .notEnrolled:
// Show alternative authentication
showPasswordLogin()
case .lockout:
// Too many attempts - user must unlock device
showLockoutAlert()
case .systemError(let message):
print("System error: \(message)")
showPasswordLogin()
default:
showPasswordLogin()
}
}
}Main entry point for biometric authentication.
// Shared singleton instance
public static let shared: DefXBiometricAuth
// Get available biometric type
public func availableBiometricType() -> BiometricType
// Check if biometric is available
public func isBiometricAvailable() -> Bool
// Authenticate user
public func authenticate(
reason: String = "Authenticate to continue",
fallbackTitle: String? = nil, // Ignored (biometrics-only mode)
completion: @escaping (Result<Void, BiometricError>) -> Void
)public enum BiometricType {
case faceID // Face ID available
case touchID // Touch ID available
case none // No biometric available
}public enum BiometricError: Error {
case notAvailable // Biometric not available
case notEnrolled // No biometric enrolled
case lockout // Too many failed attempts
case cancelled // User cancelled
case fallback // User chose fallback
case systemError(String) // System error
case unknown // Unknown error
// Stable identifier for localization
public var identifier: String
}The SDK uses biometrics-only policy by default:
- Face ID/Touch ID authentication only
- No passcode fallback option shown
fallbackTitleparameter is ignored- Apps should provide alternative authentication (e.g., password) when biometrics fail
// Uses default reason: "Authenticate to continue"
DefXBiometricAuth.shared.authenticate { result in
// Handle result
}
// Custom reason (recommended)
DefXBiometricAuth.shared.authenticate(
reason: "Login to your account"
) { result in
// Handle result
}switch error {
case .cancelled:
// User cancelled - don't show error
break
case .notAvailable, .notEnrolled:
// Biometric not usable - show password
showPasswordLogin()
case .lockout:
// Guide user to unlock device
showAlert("Too many attempts. Please unlock your device.")
case .systemError(let message):
print("System error: \(message)")
showPasswordLogin()
default:
showPasswordLogin()
}guard DefXBiometricAuth.shared.isBiometricAvailable() else {
showPasswordLogin()
return
}
DefXBiometricAuth.shared.authenticate(reason: "Login") { result in
// Handle result
}// โ BAD
authenticate(reason: "Authenticate")
// โ
GOOD
authenticate(reason: "Authenticate to view your balance")
authenticate(reason: "Confirm payment of $50.00")Since the SDK operates in biometrics-only mode, always offer password/PIN login when biometric authentication is unavailable or fails.
Simulators support biometric testing, but always verify on real devices for accurate behavior and performance.
DefXBiometric uses iOS LocalAuthentication framework with system-level security:
- Biometric data stays in Secure Enclave
- SDK never accesses raw biometric data
- Thread-safe operations
- Completion callbacks always on main thread
Recommended practices:
- Use Keychain for sensitive data storage
- Implement certificate pinning in network layer
- Add runtime security checks as needed
- Consider XCFramework distribution for basic obfuscation
For licensing, custom features, or enterprise support:
DefineX Technology Inc.
- ๐ง Email: [email protected]
- ๐ Website: https://www.definex.com
- ๐ฑ Mobile SDKs: https://github.com/Definex-Mobile
- ๐ Bug Reports: Open an issue with reproduction steps
- ๐ก Feature Requests: Describe use case and expected behavior
- ๐ง Pull Requests: Contact us first for contribution guidelines
Proprietary / Commercial License
Copyright ยฉ 2025 DefineX Technology Inc. All rights reserved.
This software is proprietary and confidential. Unauthorized copying, distribution, or use is strictly prohibited. See LICENSE file for full terms.
For licensing inquiries: [email protected]
Made with by DefineX Mobile Team