Add source code
This commit is contained in:
parent
69c08de01c
commit
0416d157d7
14 changed files with 1672 additions and 0 deletions
53
TetheringHider/Services/AuthenticationService.swift
Normal file
53
TetheringHider/Services/AuthenticationService.swift
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
import Foundation
|
||||
import LocalAuthentication
|
||||
|
||||
enum AuthenticationError: LocalizedError {
|
||||
case biometricsNotAvailable
|
||||
case authenticationFailed(String)
|
||||
case userCancelled
|
||||
|
||||
var errorDescription: String? {
|
||||
switch self {
|
||||
case .biometricsNotAvailable:
|
||||
return "Touch ID is not available on this device."
|
||||
case .authenticationFailed(let reason):
|
||||
return "Authentication failed: \(reason)"
|
||||
case .userCancelled:
|
||||
return "Authentication was cancelled."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct AuthenticationService: Sendable {
|
||||
|
||||
/// Attempts biometric authentication (Touch ID) before proceeding.
|
||||
/// Falls back gracefully if Touch ID is not available.
|
||||
/// Returns true if authenticated, false if biometrics unavailable (will proceed to admin dialog).
|
||||
func authenticateWithBiometrics() async throws -> Bool {
|
||||
let context = LAContext()
|
||||
var error: NSError?
|
||||
|
||||
guard context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &error) else {
|
||||
// Touch ID not available — skip biometric step, will use admin dialog
|
||||
return true
|
||||
}
|
||||
|
||||
do {
|
||||
let success = try await context.evaluatePolicy(
|
||||
.deviceOwnerAuthenticationWithBiometrics,
|
||||
localizedReason: "Authenticate to modify system TTL value"
|
||||
)
|
||||
return success
|
||||
} catch let authError as LAError {
|
||||
switch authError.code {
|
||||
case .userCancel, .appCancel:
|
||||
throw AuthenticationError.userCancelled
|
||||
case .userFallback:
|
||||
// User chose to use password — allow proceeding to admin dialog
|
||||
return true
|
||||
default:
|
||||
throw AuthenticationError.authenticationFailed(authError.localizedDescription)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue