Ensure that the current user is the device owner before linking a new device. (#5773)

This commit is contained in:
Doug
2026-06-26 16:24:18 +01:00
committed by GitHub
parent 3f3aa79a48
commit f3da459d16
23 changed files with 558 additions and 18 deletions
@@ -17,6 +17,7 @@ class AppLockService: AppLockServiceProtocol {
private let timer: AppLockTimer
private let unlockPolicy: LAPolicy = .deviceOwnerAuthenticationWithBiometrics
private let deviceOwnerPolicy: LAPolicy = .deviceOwnerAuthentication
var isMandatory: Bool {
appSettings.appLockIsMandatory
@@ -163,6 +164,30 @@ class AppLockService: AppLockServiceProtocol {
}
}
func verifyDeviceOwner(reason: String) async -> AppLockDeviceOwnerResult {
let context = verificationContext()
var error: NSError?
guard context.canEvaluatePolicy(deviceOwnerPolicy, error: &error) else {
MXLog.warning("Device owner verification unavailable: \(String(describing: error))")
return isEnabled ? .appLockPINRequired : .unavailable
}
do {
guard try await context.evaluatePolicy(deviceOwnerPolicy, localizedReason: reason) else {
MXLog.warning("Device owner verification completed without success.")
return .unverified
}
return .verified
} catch LAError.userCancel, LAError.systemCancel {
MXLog.info("Device owner verification was cancelled.")
return .cancelled
} catch {
MXLog.warning("Device owner verification failed: \(error)")
return .error
}
}
// MARK: - Private
/// Queries the context for supported biometrics and enrolment state.
@@ -187,6 +212,12 @@ class AppLockService: AppLockServiceProtocol {
return context
}
/// Creates a fresh context for device owner verification so the user is always prompted.
private func verificationContext() -> LAContext {
// Keep using the injected context for tests etc.
type(of: context) == LAContext.self ? LAContext() : context
}
/// Shared logic for completing an unlock via a PIN or biometrics.
private func completeUnlock() {
timer.registerUnlock()