Skip to content

Commit

Permalink
Add option for iOS/MacOS to allow non-biometric authentication (`darw…
Browse files Browse the repository at this point in the history
…inBiometricOnly`) #101
  • Loading branch information
hpoul committed Sep 20, 2023
1 parent dd4ef41 commit daae973
Show file tree
Hide file tree
Showing 11 changed files with 49 additions and 12 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
## 5.0.1-dev.1

* Add option for iOS/MacOS to allow non-biometric authentication (`darwinBiometricOnly`) #101
* Improve [canAuthenticate] to differentiate between no available biometry and no available
user code.

## 5.0.0+4

* Add topics to pubspec.yaml
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ enum class CanAuthenticateResponse(val code: Int) {
ErrorNoBiometricEnrolled(BiometricManager.BIOMETRIC_ERROR_NONE_ENROLLED),
ErrorNoHardware(BiometricManager.BIOMETRIC_ERROR_NO_HARDWARE),
ErrorStatusUnknown(BiometricManager.BIOMETRIC_STATUS_UNKNOWN),
ErrorPasscodeNotSet(-99),
;

override fun toString(): String {
Expand Down Expand Up @@ -317,6 +318,12 @@ class BiometricStoragePlugin : FlutterPlugin, ActivityAware, MethodCallHandler {
}

private fun canAuthenticate(): CanAuthenticateResponse {
val credentialsResponse = biometricManager.canAuthenticate(DEVICE_CREDENTIAL);
logger.debug { "canAuthenticate for DEVICE_CREDENTIAL: $credentialsResponse" }
if (credentialsResponse == BiometricManager.BIOMETRIC_ERROR_NONE_ENROLLED) {
return CanAuthenticateResponse.Success
}

val response = biometricManager.canAuthenticate(
BIOMETRIC_STRONG or BIOMETRIC_WEAK
)
Expand Down
4 changes: 2 additions & 2 deletions example/ios/Flutter/Flutter.podspec
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#
# NOTE: This podspec is NOT to be published. It is only used as a local source!
# This is a generated file; do not edit or check into version control.
# This podspec is NOT to be published. It is only used as a local source!
# This is a generated file; do not edit or check into version control.
#

Pod::Spec.new do |s|
Expand Down
2 changes: 1 addition & 1 deletion example/ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,4 @@ SPEC CHECKSUMS:

PODFILE CHECKSUM: ef19549a9bc3046e7bb7d2fab4d021637c0c58a3

COCOAPODS: 1.11.3
COCOAPODS: 1.12.1
7 changes: 5 additions & 2 deletions example/ios/Runner.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
archiveVersion = 1;
classes = {
};
objectVersion = 50;
objectVersion = 54;
objects = {

/* Begin PBXBuildFile section */
Expand Down Expand Up @@ -163,7 +163,7 @@
97C146E61CF9000F007C117D /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 1300;
LastUpgradeCheck = 1430;
ORGANIZATIONNAME = "The Chromium Authors";
TargetAttributes = {
97C146ED1CF9000F007C117D = {
Expand Down Expand Up @@ -208,10 +208,12 @@
/* Begin PBXShellScriptBuildPhase section */
3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
isa = PBXShellScriptBuildPhase;
alwaysOutOfDate = 1;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
"${TARGET_BUILD_DIR}/${INFOPLIST_PATH}",
);
name = "Thin Binary";
outputPaths = (
Expand Down Expand Up @@ -244,6 +246,7 @@
};
9740EEB61CF901F6004384FC /* Run Script */ = {
isa = PBXShellScriptBuildPhase;
alwaysOutOfDate = 1;
buildActionMask = 2147483647;
files = (
);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1300"
LastUpgradeVersion = "1430"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
Expand Down
2 changes: 2 additions & 0 deletions example/ios/Runner/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -45,5 +45,7 @@
<false/>
<key>CADisableMinimumFrameDurationOnPhone</key>
<true/>
<key>UIApplicationSupportsIndirectInputEvents</key>
<true/>
</dict>
</plist>
2 changes: 1 addition & 1 deletion example/pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ packages:
path: ".."
relative: true
source: path
version: "5.0.0"
version: "5.0.0+4"
boolean_selector:
dependency: transitive
description:
Expand Down
11 changes: 11 additions & 0 deletions lib/src/biometric_storage.dart
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ enum CanAuthenticateResponse {
errorNoBiometricEnrolled,
errorNoHardware,

/// Passcode is not set (iOS/MacOS) or no user credentials (on macos).
errorPasscodeNotSet,

/// Used on android if the status is unknown.
/// https://developer.android.com/reference/androidx/biometric/BiometricManager#BIOMETRIC_STATUS_UNKNOWN
statusUnknown,
Expand All @@ -31,6 +34,7 @@ const _canAuthenticateMapping = {
'ErrorHwUnavailable': CanAuthenticateResponse.errorHwUnavailable,
'ErrorNoBiometricEnrolled': CanAuthenticateResponse.errorNoBiometricEnrolled,
'ErrorNoHardware': CanAuthenticateResponse.errorNoHardware,
'ErrorPasscodeNotSet': CanAuthenticateResponse.errorPasscodeNotSet,
'ErrorUnknown': CanAuthenticateResponse.unsupported,
'ErrorStatusUnknown': CanAuthenticateResponse.statusUnknown,
};
Expand Down Expand Up @@ -83,6 +87,7 @@ class StorageFileInitOptions {
this.authenticationValidityDurationSeconds = -1,
this.authenticationRequired = true,
this.androidBiometricOnly = true,
this.darwinBiometricOnly = true,
});

final int authenticationValidityDurationSeconds;
Expand All @@ -102,11 +107,17 @@ class StorageFileInitOptions {
/// https://github.com/authpass/biometric_storage/issues/12#issuecomment-902508609
final bool androidBiometricOnly;

/// Only for iOS and macOS:
/// Uses `.biometryCurrentSet` if true, `.userPresence` otherwise.
/// https://developer.apple.com/documentation/security/secaccesscontrolcreateflags/1392879-userpresence
final bool darwinBiometricOnly;

Map<String, dynamic> toJson() => <String, dynamic>{
'authenticationValidityDurationSeconds':
authenticationValidityDurationSeconds,
'authenticationRequired': authenticationRequired,
'androidBiometricOnly': androidBiometricOnly,
'darwinBiometricOnly': darwinBiometricOnly,
};
}

Expand Down
16 changes: 12 additions & 4 deletions macos/Classes/BiometricStorageImpl.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,11 @@ class InitOptions {
init(params: [String: Any]) {
authenticationValidityDurationSeconds = params["authenticationValidityDurationSeconds"] as? Int
authenticationRequired = params["authenticationRequired"] as? Bool
darwinBiometricOnly = params["darwinBiometricOnly"] as? Bool
}
let authenticationValidityDurationSeconds: Int!
let authenticationRequired: Bool!
let darwinBiometricOnly: Bool!
}

class IOSPromptInfo {
Expand Down Expand Up @@ -136,7 +138,9 @@ class BiometricStorageImpl {
case .touchIDNotAvailable:
result("ErrorHwUnavailable")
break;
case .passcodeNotSet: fallthrough
case .passcodeNotSet:
result("ErrorPasscodeNotSet")
break;
case .touchIDNotEnrolled:
result("ErrorNoBiometricEnrolled")
break;
Expand Down Expand Up @@ -194,10 +198,14 @@ class BiometricStorageFile {
private func accessControl(_ result: @escaping StorageCallback) -> SecAccessControl? {
let accessControlFlags: SecAccessControlCreateFlags

if #available(iOS 11.3, *) {
accessControlFlags = .biometryCurrentSet
if initOptions.darwinBiometricOnly {
if #available(iOS 11.3, *) {
accessControlFlags = .biometryCurrentSet
} else {
accessControlFlags = .touchIDCurrentSet
}
} else {
accessControlFlags = .touchIDCurrentSet
accessControlFlags = .userPresence
}

// access = SecAccessControlCreateWithFlags(nil,
Expand Down
2 changes: 1 addition & 1 deletion pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: biometric_storage
description: |
Secure Storage: Encrypted data store optionally secured by biometric lock with support
for iOS, Android, MacOS. Partial support for Linux, Windows and web (localStorage).
version: 5.0.0+4
version: 5.0.1-dev.1
homepage: https://github.com/authpass/biometric_storage/

environment:
Expand Down

0 comments on commit daae973

Please sign in to comment.