expo-local-authentication 13.0.2 → 13.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -10,6 +10,18 @@
10
10
 
11
11
  ### 💡 Others
12
12
 
13
+ ## 13.2.0 — 2023-02-03
14
+
15
+ ### 💡 Others
16
+
17
+ - On Android bump `compileSdkVersion` and `targetSdkVersion` to `33`. ([#20721](https://github.com/expo/expo/pull/20721) by [@lukmccall](https://github.com/lukmccall))
18
+
19
+ ## 13.1.0 — 2022-12-30
20
+
21
+ ### 🎉 New features
22
+
23
+ - Native module on iOS is now written in Swift using the Sweet API. ([#19980](https://github.com/expo/expo/pull/19980) by [@fobos531](https://github.com/fobos531))
24
+
13
25
  ## 13.0.2 — 2022-11-02
14
26
 
15
27
  _This version does not introduce any user-facing changes._
package/README.md CHANGED
@@ -4,7 +4,7 @@ Provides an API for FaceID and TouchID (iOS) or the Fingerprint API (Android) to
4
4
 
5
5
  # API documentation
6
6
 
7
- - [Documentation for the main branch](https://github.com/expo/expo/blob/main/docs/pages/versions/unversioned/sdk/local-authentication.md)
7
+ - [Documentation for the main branch](https://github.com/expo/expo/blob/main/docs/pages/versions/unversioned/sdk/local-authentication.mdx)
8
8
  - [Documentation for the latest stable release](https://docs.expo.dev/versions/latest/sdk/local-authentication/)
9
9
 
10
10
  # Installation in managed Expo projects
@@ -3,7 +3,7 @@ apply plugin: 'kotlin-android'
3
3
  apply plugin: 'maven-publish'
4
4
 
5
5
  group = 'host.exp.exponent'
6
- version = '13.0.2'
6
+ version = '13.2.0'
7
7
 
8
8
  buildscript {
9
9
  def expoModulesCorePlugin = new File(project(":expo-modules-core").projectDir.absolutePath, "ExpoModulesCorePlugin.gradle")
@@ -59,7 +59,7 @@ afterEvaluate {
59
59
  }
60
60
 
61
61
  android {
62
- compileSdkVersion safeExtGet("compileSdkVersion", 31)
62
+ compileSdkVersion safeExtGet("compileSdkVersion", 33)
63
63
 
64
64
  compileOptions {
65
65
  sourceCompatibility JavaVersion.VERSION_11
@@ -72,9 +72,9 @@ android {
72
72
 
73
73
  defaultConfig {
74
74
  minSdkVersion safeExtGet("minSdkVersion", 21)
75
- targetSdkVersion safeExtGet("targetSdkVersion", 31)
75
+ targetSdkVersion safeExtGet("targetSdkVersion", 33)
76
76
  versionCode 30
77
- versionName "13.0.2"
77
+ versionName "13.2.0"
78
78
  }
79
79
  lintOptions {
80
80
  abortOnError false
@@ -1,3 +1,3 @@
1
- declare const _default: import("expo-modules-core").ProxyNativeModule;
1
+ declare const _default: any;
2
2
  export default _default;
3
3
  //# sourceMappingURL=ExpoLocalAuthentication.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ExpoLocalAuthentication.d.ts","sourceRoot":"","sources":["../src/ExpoLocalAuthentication.ts"],"names":[],"mappings":";AAEA,wBAA0D"}
1
+ {"version":3,"file":"ExpoLocalAuthentication.d.ts","sourceRoot":"","sources":["../src/ExpoLocalAuthentication.ts"],"names":[],"mappings":";AAEA,wBAA8D"}
@@ -1,3 +1,3 @@
1
- import { NativeModulesProxy } from 'expo-modules-core';
2
- export default NativeModulesProxy.ExpoLocalAuthentication;
1
+ import { requireNativeModule } from 'expo-modules-core';
2
+ export default requireNativeModule('ExpoLocalAuthentication');
3
3
  //# sourceMappingURL=ExpoLocalAuthentication.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ExpoLocalAuthentication.js","sourceRoot":"","sources":["../src/ExpoLocalAuthentication.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAEvD,eAAe,kBAAkB,CAAC,uBAAuB,CAAC","sourcesContent":["import { NativeModulesProxy } from 'expo-modules-core';\n\nexport default NativeModulesProxy.ExpoLocalAuthentication;\n"]}
1
+ {"version":3,"file":"ExpoLocalAuthentication.js","sourceRoot":"","sources":["../src/ExpoLocalAuthentication.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAExD,eAAe,mBAAmB,CAAC,yBAAyB,CAAC,CAAC","sourcesContent":["import { requireNativeModule } from 'expo-modules-core';\n\nexport default requireNativeModule('ExpoLocalAuthentication');\n"]}
@@ -1,4 +1,4 @@
1
- export declare type LocalAuthenticationResult = {
1
+ export type LocalAuthenticationResult = {
2
2
  success: true;
3
3
  } | {
4
4
  success: false;
@@ -34,7 +34,7 @@ export declare enum SecurityLevel {
34
34
  */
35
35
  BIOMETRIC = 2
36
36
  }
37
- export declare type LocalAuthenticationOptions = {
37
+ export type LocalAuthenticationOptions = {
38
38
  /**
39
39
  * A message that is shown alongside the TouchID or FaceID prompt.
40
40
  */
@@ -1 +1 @@
1
- {"version":3,"file":"LocalAuthentication.types.d.ts","sourceRoot":"","sources":["../src/LocalAuthentication.types.ts"],"names":[],"mappings":"AAAA,oBAAY,yBAAyB,GACjC;IAAE,OAAO,EAAE,IAAI,CAAA;CAAE,GACjB;IAAE,OAAO,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAGxD,oBAAY,kBAAkB;IAC5B;;OAEG;IACH,WAAW,IAAI;IACf;;OAEG;IACH,kBAAkB,IAAI;IACtB;;;OAGG;IACH,IAAI,IAAI;CACT;AAGD,oBAAY,aAAa;IACvB;;OAEG;IACH,IAAI,IAAI;IACR;;OAEG;IACH,MAAM,IAAI;IACV;;OAEG;IACH,SAAS,IAAI;CACd;AAGD,oBAAY,0BAA0B,GAAG;IACvC;;OAEG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;;;;OAOG;IACH,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC;;;;;OAKG;IACH,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B;;;;;OAKG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB,CAAC"}
1
+ {"version":3,"file":"LocalAuthentication.types.d.ts","sourceRoot":"","sources":["../src/LocalAuthentication.types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,yBAAyB,GACjC;IAAE,OAAO,EAAE,IAAI,CAAA;CAAE,GACjB;IAAE,OAAO,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAGxD,oBAAY,kBAAkB;IAC5B;;OAEG;IACH,WAAW,IAAI;IACf;;OAEG;IACH,kBAAkB,IAAI;IACtB;;;OAGG;IACH,IAAI,IAAI;CACT;AAGD,oBAAY,aAAa;IACvB;;OAEG;IACH,IAAI,IAAI;IACR;;OAEG;IACH,MAAM,IAAI;IACV;;OAEG;IACH,SAAS,IAAI;CACd;AAGD,MAAM,MAAM,0BAA0B,GAAG;IACvC;;OAEG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;;;;OAOG;IACH,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC;;;;;OAKG;IACH,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B;;;;;OAKG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB,CAAC"}
@@ -0,0 +1,7 @@
1
+ {
2
+ "name": "expo-local-authentication",
3
+ "platforms": ["ios", "android"],
4
+ "ios": {
5
+ "modules": ["LocalAuthenticationModule"]
6
+ }
7
+ }
@@ -3,7 +3,7 @@ require 'json'
3
3
  package = JSON.parse(File.read(File.join(__dir__, '..', 'package.json')))
4
4
 
5
5
  Pod::Spec.new do |s|
6
- s.name = 'EXLocalAuthentication'
6
+ s.name = 'ExpoLocalAuthentication'
7
7
  s.version = package['version']
8
8
  s.summary = package['description']
9
9
  s.description = package['description']
@@ -11,15 +11,22 @@ Pod::Spec.new do |s|
11
11
  s.author = package['author']
12
12
  s.homepage = package['homepage']
13
13
  s.platform = :ios, '13.0'
14
+ s.swift_version = '5.4'
14
15
  s.source = { git: 'https://github.com/expo/expo.git' }
15
16
  s.static_framework = true
16
17
 
17
18
  s.dependency 'ExpoModulesCore'
18
19
 
20
+ # Swift/Objective-C compatibility
21
+ s.pod_target_xcconfig = {
22
+ 'DEFINES_MODULE' => 'YES',
23
+ 'SWIFT_COMPILATION_MODE' => 'wholemodule'
24
+ }
25
+
19
26
  if !$ExpoUseSources&.include?(package['name']) && ENV['EXPO_USE_SOURCE'].to_i == 0 && File.exist?("#{s.name}.xcframework") && Gem::Version.new(Pod::VERSION) >= Gem::Version.new('1.10.0')
20
- s.source_files = "#{s.name}/**/*.h"
27
+ s.source_files = "**/*.h"
21
28
  s.vendored_frameworks = "#{s.name}.xcframework"
22
29
  else
23
- s.source_files = "#{s.name}/**/*.{h,m}"
30
+ s.source_files = "**/*.{h,m,swift}"
24
31
  end
25
32
  end
@@ -0,0 +1,169 @@
1
+ import ExpoModulesCore
2
+ import LocalAuthentication
3
+
4
+ public class LocalAuthenticationModule: Module {
5
+ public func definition() -> ModuleDefinition {
6
+ Name("ExpoLocalAuthentication")
7
+
8
+ AsyncFunction("hasHardwareAsync") { () -> Bool in
9
+ let context = LAContext()
10
+ var error: NSError?
11
+ let isSupported: Bool = context.canEvaluatePolicy(LAPolicy.deviceOwnerAuthenticationWithBiometrics, error: &error)
12
+ let isAvailable: Bool = isSupported || error?.code != LAError.biometryNotAvailable.rawValue
13
+
14
+ return isAvailable
15
+ }
16
+
17
+ AsyncFunction("isEnrolledAsync") { () -> Bool in
18
+ let context = LAContext()
19
+ var error: NSError?
20
+ let isSupported: Bool = context.canEvaluatePolicy(LAPolicy.deviceOwnerAuthenticationWithBiometrics, error: &error)
21
+ let isEnrolled: Bool = isSupported && error == nil
22
+
23
+ return isEnrolled
24
+ }
25
+
26
+ AsyncFunction("supportedAuthenticationTypesAsync") { () -> [Int] in
27
+ var supportedAuthenticationTypes: [Int] = []
28
+
29
+ if isTouchIdDevice() {
30
+ supportedAuthenticationTypes.append(AuthenticationType.fingerprint.rawValue)
31
+ }
32
+
33
+ if isFaceIdDevice() {
34
+ supportedAuthenticationTypes.append(AuthenticationType.facialRecognition.rawValue)
35
+ }
36
+
37
+ return supportedAuthenticationTypes
38
+ }
39
+
40
+ AsyncFunction("getEnrolledLevelAsync") { () -> Int in
41
+ let context = LAContext()
42
+ var error: NSError?
43
+
44
+ var level: Int = SecurityLevel.none.rawValue
45
+
46
+ let isAuthenticationSupported: Bool = context.canEvaluatePolicy(LAPolicy.deviceOwnerAuthentication, error: &error)
47
+ if isAuthenticationSupported && error == nil {
48
+ level = SecurityLevel.secret.rawValue
49
+ }
50
+
51
+ let isBiometricsSupported: Bool = context.canEvaluatePolicy(LAPolicy.deviceOwnerAuthenticationWithBiometrics, error: &error)
52
+
53
+ if isBiometricsSupported && error == nil {
54
+ level = SecurityLevel.biometric.rawValue
55
+ }
56
+
57
+ return level
58
+ }
59
+
60
+ AsyncFunction("authenticateAsync") { (options: LocalAuthenticationOptions, promise: Promise) -> Void in
61
+ var warningMessage: NSString?
62
+ var reason = options.promptMessage
63
+ var cancelLabel = options.cancelLabel
64
+ var fallbackLabel = options.fallbackLabel
65
+ var disableDeviceFallback = options.disableDeviceFallback
66
+
67
+ if isFaceIdDevice() {
68
+ let usageDescription = Bundle.main.object(forInfoDictionaryKey: "NSFaceIDUsageDescription")
69
+
70
+ if usageDescription != nil {
71
+ warningMessage = "FaceID is available but has not been configured. To enable FaceID, provide `NSFaceIDUsageDescription`."
72
+ }
73
+ }
74
+
75
+ let context = LAContext()
76
+
77
+ if fallbackLabel != nil {
78
+ context.localizedFallbackTitle = fallbackLabel
79
+ }
80
+
81
+ if cancelLabel != nil {
82
+ context.localizedCancelTitle = cancelLabel
83
+ }
84
+
85
+ context.interactionNotAllowed = false
86
+
87
+ let policyForAuth: LAPolicy = disableDeviceFallback ? LAPolicy.deviceOwnerAuthenticationWithBiometrics : LAPolicy.deviceOwnerAuthentication
88
+
89
+ if disableDeviceFallback {
90
+ if warningMessage != nil {
91
+ // If the warning message is set (NSFaceIDUsageDescription is not configured) then we can't use
92
+ // authentication with biometrics — it would crash, so let's just resolve with no success.
93
+ // We could reject, but we already resolve even if there are any errors, so sadly we would need to introduce a breaking change.
94
+ return promise.resolve([
95
+ "success": false,
96
+ "error": "missing_usage_description",
97
+ "warning": warningMessage
98
+ ])
99
+ }
100
+ }
101
+
102
+ context.evaluatePolicy(policyForAuth, localizedReason: reason ?? "") { success, error in
103
+ var err: String?
104
+
105
+ if let error = error as? NSError {
106
+ err = convertErrorCode(error: error)
107
+ }
108
+
109
+ return promise.resolve([
110
+ "success": success,
111
+ "error": err,
112
+ "warning": warningMessage
113
+ ])
114
+ }
115
+ }
116
+ }
117
+ }
118
+
119
+ func isFaceIdDevice() -> Bool {
120
+ let context = LAContext()
121
+ context.canEvaluatePolicy(LAPolicy.deviceOwnerAuthenticationWithBiometrics, error: nil)
122
+
123
+ return context.biometryType == LABiometryType.faceID
124
+ }
125
+
126
+ func isTouchIdDevice() -> Bool {
127
+ let context = LAContext()
128
+ context.canEvaluatePolicy(LAPolicy.deviceOwnerAuthenticationWithBiometrics, error: nil)
129
+
130
+ return context.biometryType == LABiometryType.touchID
131
+ }
132
+
133
+ func convertErrorCode(error: NSError) -> String {
134
+ switch error.code {
135
+ case LAError.systemCancel.rawValue:
136
+ return "system_cancel"
137
+ case LAError.appCancel.rawValue:
138
+ return "app_cancel"
139
+ case LAError.biometryLockout.rawValue:
140
+ return "lockout"
141
+ case LAError.userFallback.rawValue:
142
+ return "user_fallback"
143
+ case LAError.userCancel.rawValue:
144
+ return "user_cancel"
145
+ case LAError.biometryNotAvailable.rawValue:
146
+ return "not_available"
147
+ case LAError.invalidContext.rawValue:
148
+ return "invalid_context"
149
+ case LAError.biometryNotEnrolled.rawValue:
150
+ return "not_enrolled"
151
+ case LAError.passcodeNotSet.rawValue:
152
+ return "passcode_not_set"
153
+ case LAError.authenticationFailed.rawValue:
154
+ return "authentication_failed"
155
+ default:
156
+ return "unknown: \(error.code), \(error.localizedDescription)"
157
+ }
158
+ }
159
+
160
+ enum AuthenticationType: Int {
161
+ case fingerprint = 1
162
+ case facialRecognition = 2
163
+ }
164
+
165
+ enum SecurityLevel: Int {
166
+ case none = 0
167
+ case secret = 1
168
+ case biometric = 2
169
+ }
@@ -0,0 +1,8 @@
1
+ import ExpoModulesCore
2
+
3
+ internal struct LocalAuthenticationOptions: Record {
4
+ @Field var cancelLabel: String?
5
+ @Field var disableDeviceFallback: Bool = false
6
+ @Field var fallbackLabel: String?
7
+ @Field var promptMessage: String?
8
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "expo-local-authentication",
3
- "version": "13.0.2",
3
+ "version": "13.2.0",
4
4
  "description": "Provides an API for FaceID and TouchID (iOS) or the Fingerprint API (Android) to authenticate the user with a face or fingerprint scan.",
5
5
  "main": "build/LocalAuthentication.js",
6
6
  "types": "build/LocalAuthentication.d.ts",
@@ -46,5 +46,5 @@
46
46
  "peerDependencies": {
47
47
  "expo": "*"
48
48
  },
49
- "gitHead": "1a87dcc55895a9e16e3d4fd0fa78f2244c1d961f"
49
+ "gitHead": "1815e2eaad8c753588c7b1eb74420174a28e01f4"
50
50
  }
@@ -1,3 +1,3 @@
1
- import { NativeModulesProxy } from 'expo-modules-core';
1
+ import { requireNativeModule } from 'expo-modules-core';
2
2
 
3
- export default NativeModulesProxy.ExpoLocalAuthentication;
3
+ export default requireNativeModule('ExpoLocalAuthentication');
@@ -1,15 +0,0 @@
1
- // Copyright 2018-present 650 Industries. All rights reserved.
2
-
3
- #import <ExpoModulesCore/EXExportedModule.h>
4
- #import <ExpoModulesCore/EXModuleRegistryConsumer.h>
5
-
6
- @interface EXLocalAuthentication : EXExportedModule
7
-
8
- - (void)authenticateWithOptions:(NSDictionary *)options
9
- resolve:(EXPromiseResolveBlock)resolve
10
- reject:(EXPromiseRejectBlock)reject;
11
- - (NSString *)convertErrorCode:(NSError *)error;
12
- + (BOOL)isTouchIdDevice;
13
- + (BOOL)isFaceIdDevice;
14
-
15
- @end
@@ -1,206 +0,0 @@
1
- // Copyright 2018-present 650 Industries. All rights reserved.
2
-
3
- #import <LocalAuthentication/LocalAuthentication.h>
4
-
5
- #import <ExpoModulesCore/EXUtilities.h>
6
- #import <EXLocalAuthentication/EXLocalAuthentication.h>
7
-
8
- typedef NS_ENUM(NSInteger, EXAuthenticationType) {
9
- EXAuthenticationTypeFingerprint = 1,
10
- EXAuthenticationTypeFacialRecognition = 2,
11
- };
12
-
13
- typedef NS_ENUM(NSInteger, EXSecurityLevel) {
14
- EXSecurityLevelNone = 0,
15
- EXSecurityLevelSecret = 1,
16
- EXSecurityLevelBiometric = 2,
17
- };
18
-
19
- @implementation EXLocalAuthentication
20
-
21
- EX_EXPORT_MODULE(ExpoLocalAuthentication)
22
-
23
- EX_EXPORT_METHOD_AS(supportedAuthenticationTypesAsync,
24
- supportedAuthenticationTypesAsync:(EXPromiseResolveBlock)resolve
25
- reject:(EXPromiseRejectBlock)reject)
26
- {
27
- NSMutableArray *results = [NSMutableArray array];
28
- if ([[self class] isTouchIdDevice]) {
29
- [results addObject:@(EXAuthenticationTypeFingerprint)];
30
- }
31
- if ([[self class] isFaceIdDevice]) {
32
- [results addObject:@(EXAuthenticationTypeFacialRecognition)];
33
- }
34
- resolve(results);
35
- }
36
-
37
- EX_EXPORT_METHOD_AS(hasHardwareAsync,
38
- hasHardwareAsync:(EXPromiseResolveBlock)resolve
39
- reject:(EXPromiseRejectBlock)reject)
40
- {
41
- LAContext *context = [LAContext new];
42
- NSError *error = nil;
43
-
44
- BOOL isSupported = [context canEvaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics error:&error];
45
- BOOL isAvailable = isSupported || error.code != LAErrorBiometryNotAvailable;
46
-
47
- resolve(@(isAvailable));
48
- }
49
-
50
- EX_EXPORT_METHOD_AS(isEnrolledAsync,
51
- isEnrolledAsync:(EXPromiseResolveBlock)resolve
52
- reject:(EXPromiseRejectBlock)reject)
53
- {
54
- LAContext *context = [LAContext new];
55
- NSError *error = nil;
56
-
57
- BOOL isSupported = [context canEvaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics error:&error];
58
- BOOL isEnrolled = isSupported && error == nil;
59
-
60
- resolve(@(isEnrolled));
61
- }
62
-
63
- EX_EXPORT_METHOD_AS(getEnrolledLevelAsync,
64
- getEnrolledLevelAsync:(EXPromiseResolveBlock)resolve
65
- reject:(EXPromiseRejectBlock)reject)
66
- {
67
- LAContext *context = [LAContext new];
68
- NSError *error = nil;
69
-
70
- int level = EXSecurityLevelNone;
71
-
72
- BOOL isAuthenticationSupported = [context canEvaluatePolicy:LAPolicyDeviceOwnerAuthentication error:&error];
73
- if (isAuthenticationSupported && error == nil) {
74
- level = EXSecurityLevelSecret;
75
- }
76
- BOOL isBiometricsSupported = [context canEvaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics error:&error];
77
- if (isBiometricsSupported && error == nil) {
78
- level = EXSecurityLevelBiometric;
79
- }
80
-
81
- resolve(@(level));
82
- }
83
-
84
- EX_EXPORT_METHOD_AS(authenticateAsync,
85
- authenticateWithOptions:(NSDictionary *)options
86
- resolve:(EXPromiseResolveBlock)resolve
87
- reject:(EXPromiseRejectBlock)reject)
88
- {
89
- NSString *warningMessage;
90
- NSString *reason = options[@"promptMessage"];
91
- NSString *cancelLabel = options[@"cancelLabel"];
92
- NSString *fallbackLabel = options[@"fallbackLabel"];
93
- NSString *disableDeviceFallback = options[@"disableDeviceFallback"];
94
-
95
- if ([[self class] isFaceIdDevice]) {
96
- NSString *usageDescription = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"NSFaceIDUsageDescription"];
97
-
98
- if (!usageDescription) {
99
- warningMessage = @"FaceID is available but has not been configured. To enable FaceID, provide `NSFaceIDUsageDescription`.";
100
- }
101
- }
102
-
103
- LAContext *context = [LAContext new];
104
-
105
- if (fallbackLabel != nil) {
106
- context.localizedFallbackTitle = fallbackLabel;
107
- }
108
-
109
- if (cancelLabel != nil) {
110
- context.localizedCancelTitle = cancelLabel;
111
- }
112
-
113
- context.interactionNotAllowed = false;
114
-
115
- if ([disableDeviceFallback boolValue]) {
116
- if (warningMessage) {
117
- // If the warning message is set (NSFaceIDUsageDescription is not configured) then we can't use
118
- // authentication with biometrics — it would crash, so let's just resolve with no success.
119
- // We could reject, but we already resolve even if there are any errors, so sadly we would need to introduce a breaking change.
120
- return resolve(@{
121
- @"success": @NO,
122
- @"error": @"missing_usage_description",
123
- @"warning": warningMessage
124
- });
125
- }
126
- [context evaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics
127
- localizedReason:reason
128
- reply:^(BOOL success, NSError *error) {
129
- resolve(@{
130
- @"success": @(success),
131
- @"error": error == nil ? [NSNull null] : [self convertErrorCode:error],
132
- @"warning": EXNullIfNil(warningMessage),
133
- });
134
- }];
135
- } else {
136
- [context evaluatePolicy:LAPolicyDeviceOwnerAuthentication
137
- localizedReason:reason
138
- reply:^(BOOL success, NSError *error) {
139
- resolve(@{
140
- @"success": @(success),
141
- @"error": error == nil ? [NSNull null] : [self convertErrorCode:error],
142
- @"warning": EXNullIfNil(warningMessage),
143
- });
144
- }];
145
- }
146
-
147
- }
148
-
149
- - (NSString *)convertErrorCode:(NSError *)error
150
- {
151
- switch (error.code) {
152
- case LAErrorSystemCancel:
153
- return @"system_cancel";
154
- case LAErrorAppCancel:
155
- return @"app_cancel";
156
- case LAErrorTouchIDLockout:
157
- return @"lockout";
158
- case LAErrorUserFallback:
159
- return @"user_fallback";
160
- case LAErrorUserCancel:
161
- return @"user_cancel";
162
- case LAErrorTouchIDNotAvailable:
163
- return @"not_available";
164
- case LAErrorInvalidContext:
165
- return @"invalid_context";
166
- case LAErrorTouchIDNotEnrolled:
167
- return @"not_enrolled";
168
- case LAErrorPasscodeNotSet:
169
- return @"passcode_not_set";
170
- case LAErrorAuthenticationFailed:
171
- return @"authentication_failed";
172
- default:
173
- return [@"unknown: " stringByAppendingFormat:@"%ld, %@", (long) error.code, error.localizedDescription];
174
- }
175
- }
176
-
177
- + (BOOL)isFaceIdDevice
178
- {
179
- static BOOL isFaceIDDevice = NO;
180
-
181
- static dispatch_once_t onceToken;
182
-
183
- dispatch_once(&onceToken, ^{
184
- LAContext *context = [LAContext new];
185
- [context canEvaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics error:nil];
186
- isFaceIDDevice = context.biometryType == LABiometryTypeFaceID;
187
- });
188
-
189
- return isFaceIDDevice;
190
- }
191
-
192
- + (BOOL)isTouchIdDevice
193
- {
194
- static BOOL isTouchIDDevice = NO;
195
- static dispatch_once_t onceToken;
196
-
197
- dispatch_once(&onceToken, ^{
198
- LAContext *context = [LAContext new];
199
- [context canEvaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics error:nil];
200
- isTouchIDDevice = context.biometryType == LABiometryTypeTouchID;
201
- });
202
-
203
- return isTouchIDDevice;
204
- }
205
-
206
- @end
package/unimodule.json DELETED
@@ -1,4 +0,0 @@
1
- {
2
- "name": "expo-local-authentication",
3
- "platforms": ["ios", "android"]
4
- }