Skip to content

Commit cfc56a2

Browse files
authored
[local_auth_darwin] Handle when FaceID hardware is available but permissions have been denied for the app (#8348)
LocalAuth [`-canEvaluatePolicy::`](https://developer.apple.com/documentation/localauthentication/lacontext/canevaluatepolicy(_:error:)?language=objc) returns error `LAErrorBiometryNotAvailable` when either Face ID isn't available at the hardware level, OR the Face ID is available/setup but the permissions for the app were denied. If it returns `LAErrorBiometryNotAvailable`, also check `biometryType` since this _should_ be none if there really is no biometry, but gets populated with [`LABiometryTypeTouchID`](https://developer.apple.com/documentation/localauthentication/labiometrytype/touchid?language=objc) when the FaceID hardware is available, but permission is denied. I tried this on a iPhone 16 Pro which has Face ID but not Touch ID support. Fixes flutter/flutter#160083
1 parent 973e8b5 commit cfc56a2

File tree

4 files changed

+30
-4
lines changed

4 files changed

+30
-4
lines changed

packages/local_auth/local_auth_darwin/CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
## NEXT
1+
## 1.4.3
22

3+
* Handles when biometry hardware is available but permissions have been denied for the app.
34
* Updates minimum supported SDK version to Flutter 3.22/Dart 3.4.
45

56
## 1.4.2

packages/local_auth/local_auth_darwin/darwin/Tests/FLALocalAuthPluginTests.swift

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -447,7 +447,7 @@ class FLALocalAuthPluginTests: XCTestCase {
447447
XCTAssertNil(error)
448448
}
449449

450-
func testDeviceSupportsBiometrics_withNoBiometricHardware() {
450+
func testDeviceSupportsBiometrics_withBiometryNotAvailable() {
451451
let stubAuthContext = StubAuthContext()
452452
let alertFactory = StubAlertFactory()
453453
let viewProvider = StubViewProvider()
@@ -456,14 +456,34 @@ class FLALocalAuthPluginTests: XCTestCase {
456456
alertFactory: alertFactory, viewProvider: viewProvider)
457457

458458
stubAuthContext.expectBiometrics = true
459-
stubAuthContext.canEvaluateError = NSError(domain: "error", code: 0)
459+
stubAuthContext.canEvaluateError = NSError(
460+
domain: "error", code: LAError.biometryNotAvailable.rawValue)
460461

461462
var error: FlutterError?
462463
let result = plugin.deviceCanSupportBiometricsWithError(&error)
463464
XCTAssertFalse(result!.boolValue)
464465
XCTAssertNil(error)
465466
}
466467

468+
func testDeviceSupportsBiometrics_withBiometryNotAvailableLoadedBiometryType() {
469+
let stubAuthContext = StubAuthContext()
470+
let alertFactory = StubAlertFactory()
471+
let viewProvider = StubViewProvider()
472+
let plugin = FLALocalAuthPlugin(
473+
contextFactory: StubAuthContextFactory(contexts: [stubAuthContext]),
474+
alertFactory: alertFactory, viewProvider: viewProvider)
475+
476+
stubAuthContext.expectBiometrics = true
477+
stubAuthContext.biometryType = LABiometryType.touchID
478+
stubAuthContext.canEvaluateError = NSError(
479+
domain: "error", code: LAError.biometryNotAvailable.rawValue)
480+
481+
var error: FlutterError?
482+
let result = plugin.deviceCanSupportBiometricsWithError(&error)
483+
XCTAssertTrue(result!.boolValue)
484+
XCTAssertNil(error)
485+
}
486+
467487
func testGetEnrolledBiometricsWithFaceID() {
468488
let stubAuthContext = StubAuthContext()
469489
let alertFactory = StubAlertFactory()

packages/local_auth/local_auth_darwin/darwin/local_auth_darwin/Sources/local_auth_darwin/FLALocalAuthPlugin.m

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -317,6 +317,11 @@ - (nullable NSNumber *)deviceCanSupportBiometricsWithError:
317317
if (authError.code == LAErrorBiometryNotEnrolled) {
318318
return @YES;
319319
}
320+
// Biometry hardware is available, but possibly permissions were denied.
321+
if (authError.code == LAErrorBiometryNotAvailable &&
322+
context.biometryType != LABiometryTypeNone) {
323+
return @YES;
324+
}
320325
}
321326

322327
return @NO;

packages/local_auth/local_auth_darwin/pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ name: local_auth_darwin
22
description: iOS implementation of the local_auth plugin.
33
repository: https://github.com/flutter/packages/tree/main/packages/local_auth/local_auth_darwin
44
issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+local_auth%22
5-
version: 1.4.2
5+
version: 1.4.3
66

77
environment:
88
sdk: ^3.4.0

0 commit comments

Comments
 (0)