@capgo/capacitor-native-biometric 5.0.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.
Files changed (125) hide show
  1. package/CapgoCapacitorNativeBiometric.podspec +13 -0
  2. package/LICENSE +21 -0
  3. package/android/.gradle/8.0.2/checksums/checksums.lock +0 -0
  4. package/android/.gradle/8.0.2/dependencies-accessors/dependencies-accessors.lock +0 -0
  5. package/android/.gradle/8.0.2/dependencies-accessors/gc.properties +0 -0
  6. package/android/.gradle/8.0.2/executionHistory/executionHistory.bin +0 -0
  7. package/android/.gradle/8.0.2/executionHistory/executionHistory.lock +0 -0
  8. package/android/.gradle/8.0.2/fileChanges/last-build.bin +0 -0
  9. package/android/.gradle/8.0.2/fileHashes/fileHashes.bin +0 -0
  10. package/android/.gradle/8.0.2/fileHashes/fileHashes.lock +0 -0
  11. package/android/.gradle/8.0.2/fileHashes/resourceHashesCache.bin +0 -0
  12. package/android/.gradle/8.0.2/gc.properties +0 -0
  13. package/android/.gradle/buildOutputCleanup/buildOutputCleanup.lock +0 -0
  14. package/android/.gradle/buildOutputCleanup/cache.properties +2 -0
  15. package/android/.gradle/buildOutputCleanup/outputFiles.bin +0 -0
  16. package/android/.gradle/vcs-1/gc.properties +0 -0
  17. package/android/android.iml +40 -0
  18. package/android/build.gradle +59 -0
  19. package/android/gradle/wrapper/gradle-wrapper.jar +0 -0
  20. package/android/gradle/wrapper/gradle-wrapper.properties +6 -0
  21. package/android/gradle.properties +20 -0
  22. package/android/gradlew +244 -0
  23. package/android/gradlew.bat +92 -0
  24. package/android/local.properties +8 -0
  25. package/android/proguard-rules.pro +21 -0
  26. package/android/settings.gradle +2 -0
  27. package/android/src/androidTest/java/com/getcapacitor/android/ExampleInstrumentedTest.java +28 -0
  28. package/android/src/main/AndroidManifest.xml +12 -0
  29. package/android/src/main/java/ee/forgr/biometric/AuthActivity.java +129 -0
  30. package/android/src/main/java/ee/forgr/biometric/NativeBiometric.java +457 -0
  31. package/android/src/main/res/layout/activity_auth_acitivy.xml +12 -0
  32. package/android/src/main/res/layout/bridge_layout_main.xml +15 -0
  33. package/android/src/main/res/navigation/nav_graph.xml +28 -0
  34. package/android/src/main/res/values/colors.xml +3 -0
  35. package/android/src/main/res/values/dimens.xml +3 -0
  36. package/android/src/main/res/values/strings.xml +12 -0
  37. package/android/src/main/res/values/styles.xml +16 -0
  38. package/android/src/test/java/com/getcapacitor/ExampleUnitTest.java +18 -0
  39. package/dist/docs.json +426 -0
  40. package/dist/esm/definitions.d.ts +91 -0
  41. package/dist/esm/definitions.js +11 -0
  42. package/dist/esm/definitions.js.map +1 -0
  43. package/dist/esm/index.d.ts +4 -0
  44. package/dist/esm/index.js +7 -0
  45. package/dist/esm/index.js.map +1 -0
  46. package/dist/esm/web.d.ts +10 -0
  47. package/dist/esm/web.js +22 -0
  48. package/dist/esm/web.js.map +1 -0
  49. package/dist/plugin.cjs.js +47 -0
  50. package/dist/plugin.cjs.js.map +1 -0
  51. package/dist/plugin.js +50 -0
  52. package/dist/plugin.js.map +1 -0
  53. package/ios/Plugin/Info.plist +24 -0
  54. package/ios/Plugin/Plugin.h +10 -0
  55. package/ios/Plugin/Plugin.m +12 -0
  56. package/ios/Plugin/Plugin.swift +264 -0
  57. package/ios/Plugin.xcodeproj/project.pbxproj +554 -0
  58. package/ios/Plugin.xcodeproj/project.xcworkspace/contents.xcworkspacedata +7 -0
  59. package/ios/Plugin.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +8 -0
  60. package/ios/Plugin.xcodeproj/project.xcworkspace/xcuserdata/pilito.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
  61. package/ios/Plugin.xcodeproj/xcuserdata/jmartinez.xcuserdatad/xcschemes/xcschememanagement.plist +14 -0
  62. package/ios/Plugin.xcodeproj/xcuserdata/josemartinez.xcuserdatad/xcschemes/xcschememanagement.plist +14 -0
  63. package/ios/Plugin.xcodeproj/xcuserdata/pilito.xcuserdatad/xcschemes/xcschememanagement.plist +14 -0
  64. package/ios/Plugin.xcworkspace/contents.xcworkspacedata +10 -0
  65. package/ios/Plugin.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +8 -0
  66. package/ios/Plugin.xcworkspace/xcuserdata/jmartinez.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
  67. package/ios/Plugin.xcworkspace/xcuserdata/josemartinez.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
  68. package/ios/Plugin.xcworkspace/xcuserdata/pilito.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
  69. package/ios/PluginTests/Info.plist +22 -0
  70. package/ios/PluginTests/PluginTests.swift +35 -0
  71. package/ios/Podfile +16 -0
  72. package/ios/Podfile.lock +22 -0
  73. package/ios/Pods/Local Podspecs/Capacitor.podspec.json +34 -0
  74. package/ios/Pods/Local Podspecs/CapacitorCordova.podspec.json +26 -0
  75. package/ios/Pods/Manifest.lock +22 -0
  76. package/ios/Pods/Pods.xcodeproj/project.pbxproj +1626 -0
  77. package/ios/Pods/Pods.xcodeproj/xcuserdata/jmartinez.xcuserdatad/xcschemes/Capacitor.xcscheme +60 -0
  78. package/ios/Pods/Pods.xcodeproj/xcuserdata/jmartinez.xcuserdatad/xcschemes/CapacitorCordova.xcscheme +58 -0
  79. package/ios/Pods/Pods.xcodeproj/xcuserdata/jmartinez.xcuserdatad/xcschemes/Pods-Plugin.xcscheme +58 -0
  80. package/ios/Pods/Pods.xcodeproj/xcuserdata/jmartinez.xcuserdatad/xcschemes/Pods-PluginTests.xcscheme +58 -0
  81. package/ios/Pods/Pods.xcodeproj/xcuserdata/jmartinez.xcuserdatad/xcschemes/xcschememanagement.plist +39 -0
  82. package/ios/Pods/Pods.xcodeproj/xcuserdata/josemartinez.xcuserdatad/xcschemes/Capacitor.xcscheme +60 -0
  83. package/ios/Pods/Pods.xcodeproj/xcuserdata/josemartinez.xcuserdatad/xcschemes/CapacitorCordova.xcscheme +58 -0
  84. package/ios/Pods/Pods.xcodeproj/xcuserdata/josemartinez.xcuserdatad/xcschemes/Pods-Plugin.xcscheme +58 -0
  85. package/ios/Pods/Pods.xcodeproj/xcuserdata/josemartinez.xcuserdatad/xcschemes/Pods-PluginTests.xcscheme +58 -0
  86. package/ios/Pods/Pods.xcodeproj/xcuserdata/josemartinez.xcuserdatad/xcschemes/xcschememanagement.plist +39 -0
  87. package/ios/Pods/Pods.xcodeproj/xcuserdata/martindonadieu.xcuserdatad/xcschemes/Capacitor.xcscheme +58 -0
  88. package/ios/Pods/Pods.xcodeproj/xcuserdata/martindonadieu.xcuserdatad/xcschemes/CapacitorCordova.xcscheme +58 -0
  89. package/ios/Pods/Pods.xcodeproj/xcuserdata/martindonadieu.xcuserdatad/xcschemes/Pods-Plugin.xcscheme +58 -0
  90. package/ios/Pods/Pods.xcodeproj/xcuserdata/martindonadieu.xcuserdatad/xcschemes/Pods-PluginTests.xcscheme +58 -0
  91. package/ios/Pods/Pods.xcodeproj/xcuserdata/martindonadieu.xcuserdatad/xcschemes/xcschememanagement.plist +31 -0
  92. package/ios/Pods/Pods.xcodeproj/xcuserdata/pilito.xcuserdatad/xcschemes/xcschememanagement.plist +29 -0
  93. package/ios/Pods/Target Support Files/Capacitor/Capacitor-Info.plist +26 -0
  94. package/ios/Pods/Target Support Files/Capacitor/Capacitor-dummy.m +5 -0
  95. package/ios/Pods/Target Support Files/Capacitor/Capacitor-prefix.pch +12 -0
  96. package/ios/Pods/Target Support Files/Capacitor/Capacitor-umbrella.h +23 -0
  97. package/ios/Pods/Target Support Files/Capacitor/Capacitor.debug.xcconfig +16 -0
  98. package/ios/Pods/Target Support Files/Capacitor/Capacitor.modulemap +8 -0
  99. package/ios/Pods/Target Support Files/Capacitor/Capacitor.release.xcconfig +16 -0
  100. package/ios/Pods/Target Support Files/CapacitorCordova/CapacitorCordova-Info.plist +26 -0
  101. package/ios/Pods/Target Support Files/CapacitorCordova/CapacitorCordova-dummy.m +5 -0
  102. package/ios/Pods/Target Support Files/CapacitorCordova/CapacitorCordova-prefix.pch +12 -0
  103. package/ios/Pods/Target Support Files/CapacitorCordova/CapacitorCordova-umbrella.h +32 -0
  104. package/ios/Pods/Target Support Files/CapacitorCordova/CapacitorCordova.debug.xcconfig +13 -0
  105. package/ios/Pods/Target Support Files/CapacitorCordova/CapacitorCordova.modulemap +6 -0
  106. package/ios/Pods/Target Support Files/CapacitorCordova/CapacitorCordova.release.xcconfig +13 -0
  107. package/ios/Pods/Target Support Files/Pods-Plugin/Pods-Plugin-Info.plist +26 -0
  108. package/ios/Pods/Target Support Files/Pods-Plugin/Pods-Plugin-acknowledgements.markdown +53 -0
  109. package/ios/Pods/Target Support Files/Pods-Plugin/Pods-Plugin-acknowledgements.plist +91 -0
  110. package/ios/Pods/Target Support Files/Pods-Plugin/Pods-Plugin-dummy.m +5 -0
  111. package/ios/Pods/Target Support Files/Pods-Plugin/Pods-Plugin-umbrella.h +16 -0
  112. package/ios/Pods/Target Support Files/Pods-Plugin/Pods-Plugin.debug.xcconfig +14 -0
  113. package/ios/Pods/Target Support Files/Pods-Plugin/Pods-Plugin.modulemap +6 -0
  114. package/ios/Pods/Target Support Files/Pods-Plugin/Pods-Plugin.release.xcconfig +14 -0
  115. package/ios/Pods/Target Support Files/Pods-PluginTests/Pods-PluginTests-Info.plist +26 -0
  116. package/ios/Pods/Target Support Files/Pods-PluginTests/Pods-PluginTests-acknowledgements.markdown +53 -0
  117. package/ios/Pods/Target Support Files/Pods-PluginTests/Pods-PluginTests-acknowledgements.plist +91 -0
  118. package/ios/Pods/Target Support Files/Pods-PluginTests/Pods-PluginTests-dummy.m +5 -0
  119. package/ios/Pods/Target Support Files/Pods-PluginTests/Pods-PluginTests-frameworks.sh +188 -0
  120. package/ios/Pods/Target Support Files/Pods-PluginTests/Pods-PluginTests-umbrella.h +16 -0
  121. package/ios/Pods/Target Support Files/Pods-PluginTests/Pods-PluginTests.debug.xcconfig +15 -0
  122. package/ios/Pods/Target Support Files/Pods-PluginTests/Pods-PluginTests.modulemap +6 -0
  123. package/ios/Pods/Target Support Files/Pods-PluginTests/Pods-PluginTests.release.xcconfig +15 -0
  124. package/package.json +80 -0
  125. package/readme.md +284 -0
package/dist/plugin.js ADDED
@@ -0,0 +1,50 @@
1
+ var capacitorApp = (function (exports, core) {
2
+ 'use strict';
3
+
4
+ exports.BiometryType = void 0;
5
+ (function (BiometryType) {
6
+ BiometryType[BiometryType["NONE"] = 0] = "NONE";
7
+ BiometryType[BiometryType["TOUCH_ID"] = 1] = "TOUCH_ID";
8
+ BiometryType[BiometryType["FACE_ID"] = 2] = "FACE_ID";
9
+ BiometryType[BiometryType["FINGERPRINT"] = 3] = "FINGERPRINT";
10
+ BiometryType[BiometryType["FACE_AUTHENTICATION"] = 4] = "FACE_AUTHENTICATION";
11
+ BiometryType[BiometryType["IRIS_AUTHENTICATION"] = 5] = "IRIS_AUTHENTICATION";
12
+ BiometryType[BiometryType["MULTIPLE"] = 6] = "MULTIPLE";
13
+ })(exports.BiometryType || (exports.BiometryType = {}));
14
+
15
+ const NativeBiometric = core.registerPlugin("NativeBiometric", {
16
+ web: () => Promise.resolve().then(function () { return web; }).then((m) => new m.NativeBiometricWeb()),
17
+ });
18
+
19
+ class NativeBiometricWeb extends core.WebPlugin {
20
+ constructor() {
21
+ super();
22
+ }
23
+ isAvailable() {
24
+ throw new Error("Method not implemented.");
25
+ }
26
+ verifyIdentity(_options) {
27
+ throw new Error("Method not implemented.");
28
+ }
29
+ getCredentials(_options) {
30
+ throw new Error("Method not implemented.");
31
+ }
32
+ setCredentials(_options) {
33
+ throw new Error("Method not implemented.");
34
+ }
35
+ deleteCredentials(_options) {
36
+ throw new Error("Method not implemented.");
37
+ }
38
+ }
39
+
40
+ var web = /*#__PURE__*/Object.freeze({
41
+ __proto__: null,
42
+ NativeBiometricWeb: NativeBiometricWeb
43
+ });
44
+
45
+ exports.NativeBiometric = NativeBiometric;
46
+
47
+ return exports;
48
+
49
+ })({}, capacitorExports);
50
+ //# sourceMappingURL=plugin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin.js","sources":["esm/definitions.js","esm/index.js","esm/web.js"],"sourcesContent":["export var BiometryType;\n(function (BiometryType) {\n BiometryType[BiometryType[\"NONE\"] = 0] = \"NONE\";\n BiometryType[BiometryType[\"TOUCH_ID\"] = 1] = \"TOUCH_ID\";\n BiometryType[BiometryType[\"FACE_ID\"] = 2] = \"FACE_ID\";\n BiometryType[BiometryType[\"FINGERPRINT\"] = 3] = \"FINGERPRINT\";\n BiometryType[BiometryType[\"FACE_AUTHENTICATION\"] = 4] = \"FACE_AUTHENTICATION\";\n BiometryType[BiometryType[\"IRIS_AUTHENTICATION\"] = 5] = \"IRIS_AUTHENTICATION\";\n BiometryType[BiometryType[\"MULTIPLE\"] = 6] = \"MULTIPLE\";\n})(BiometryType || (BiometryType = {}));\n//# sourceMappingURL=definitions.js.map","import { registerPlugin } from \"@capacitor/core\";\nconst NativeBiometric = registerPlugin(\"NativeBiometric\", {\n web: () => import(\"./web\").then((m) => new m.NativeBiometricWeb()),\n});\nexport * from \"./definitions\";\nexport { NativeBiometric };\n//# sourceMappingURL=index.js.map","import { WebPlugin } from \"@capacitor/core\";\nexport class NativeBiometricWeb extends WebPlugin {\n constructor() {\n super();\n }\n isAvailable() {\n throw new Error(\"Method not implemented.\");\n }\n verifyIdentity(_options) {\n throw new Error(\"Method not implemented.\");\n }\n getCredentials(_options) {\n throw new Error(\"Method not implemented.\");\n }\n setCredentials(_options) {\n throw new Error(\"Method not implemented.\");\n }\n deleteCredentials(_options) {\n throw new Error(\"Method not implemented.\");\n }\n}\n//# sourceMappingURL=web.js.map"],"names":["BiometryType","registerPlugin","WebPlugin"],"mappings":";;;AAAWA,kCAAa;IACxB,CAAC,UAAU,YAAY,EAAE;IACzB,IAAI,YAAY,CAAC,YAAY,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,MAAM,CAAC;IACpD,IAAI,YAAY,CAAC,YAAY,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,GAAG,UAAU,CAAC;IAC5D,IAAI,YAAY,CAAC,YAAY,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,GAAG,SAAS,CAAC;IAC1D,IAAI,YAAY,CAAC,YAAY,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,GAAG,aAAa,CAAC;IAClE,IAAI,YAAY,CAAC,YAAY,CAAC,qBAAqB,CAAC,GAAG,CAAC,CAAC,GAAG,qBAAqB,CAAC;IAClF,IAAI,YAAY,CAAC,YAAY,CAAC,qBAAqB,CAAC,GAAG,CAAC,CAAC,GAAG,qBAAqB,CAAC;IAClF,IAAI,YAAY,CAAC,YAAY,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,GAAG,UAAU,CAAC;IAC5D,CAAC,EAAEA,oBAAY,KAAKA,oBAAY,GAAG,EAAE,CAAC,CAAC;;ACRlC,UAAC,eAAe,GAAGC,mBAAc,CAAC,iBAAiB,EAAE;IAC1D,IAAI,GAAG,EAAE,MAAM,mDAAe,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,kBAAkB,EAAE,CAAC;IACtE,CAAC;;ICFM,MAAM,kBAAkB,SAASC,cAAS,CAAC;IAClD,IAAI,WAAW,GAAG;IAClB,QAAQ,KAAK,EAAE,CAAC;IAChB,KAAK;IACL,IAAI,WAAW,GAAG;IAClB,QAAQ,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;IACnD,KAAK;IACL,IAAI,cAAc,CAAC,QAAQ,EAAE;IAC7B,QAAQ,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;IACnD,KAAK;IACL,IAAI,cAAc,CAAC,QAAQ,EAAE;IAC7B,QAAQ,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;IACnD,KAAK;IACL,IAAI,cAAc,CAAC,QAAQ,EAAE;IAC7B,QAAQ,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;IACnD,KAAK;IACL,IAAI,iBAAiB,CAAC,QAAQ,EAAE;IAChC,QAAQ,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;IACnD,KAAK;IACL;;;;;;;;;;;;;;;"}
@@ -0,0 +1,24 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
+ <plist version="1.0">
4
+ <dict>
5
+ <key>CFBundleDevelopmentRegion</key>
6
+ <string>$(DEVELOPMENT_LANGUAGE)</string>
7
+ <key>CFBundleExecutable</key>
8
+ <string>$(EXECUTABLE_NAME)</string>
9
+ <key>CFBundleIdentifier</key>
10
+ <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
11
+ <key>CFBundleInfoDictionaryVersion</key>
12
+ <string>6.0</string>
13
+ <key>CFBundleName</key>
14
+ <string>$(PRODUCT_NAME)</string>
15
+ <key>CFBundlePackageType</key>
16
+ <string>FMWK</string>
17
+ <key>CFBundleShortVersionString</key>
18
+ <string>1.0</string>
19
+ <key>CFBundleVersion</key>
20
+ <string>$(CURRENT_PROJECT_VERSION)</string>
21
+ <key>NSPrincipalClass</key>
22
+ <string></string>
23
+ </dict>
24
+ </plist>
@@ -0,0 +1,10 @@
1
+ #import <UIKit/UIKit.h>
2
+
3
+ //! Project version number for Plugin.
4
+ FOUNDATION_EXPORT double PluginVersionNumber;
5
+
6
+ //! Project version string for Plugin.
7
+ FOUNDATION_EXPORT const unsigned char PluginVersionString[];
8
+
9
+ // In this header, you should import all the public headers of your framework using statements like #import <Plugin/PublicHeader.h>
10
+
@@ -0,0 +1,12 @@
1
+ #import <Foundation/Foundation.h>
2
+ #import <Capacitor/Capacitor.h>
3
+
4
+ // Define the plugin using the CAP_PLUGIN Macro, and
5
+ // each method the plugin supports using the CAP_PLUGIN_METHOD macro.
6
+ CAP_PLUGIN(NativeBiometric, "NativeBiometric",
7
+ CAP_PLUGIN_METHOD(isAvailable, CAPPluginReturnPromise);
8
+ CAP_PLUGIN_METHOD(verifyIdentity, CAPPluginReturnPromise);
9
+ CAP_PLUGIN_METHOD(getCredentials, CAPPluginReturnPromise);
10
+ CAP_PLUGIN_METHOD(setCredentials, CAPPluginReturnPromise);
11
+ CAP_PLUGIN_METHOD(deleteCredentials, CAPPluginReturnPromise);
12
+ )
@@ -0,0 +1,264 @@
1
+ import Foundation
2
+ import Capacitor
3
+ import LocalAuthentication
4
+
5
+ /**
6
+ * Please read the Capacitor iOS Plugin Development Guide
7
+ * here: https://capacitor.ionicframework.com/docs/plugins/ios
8
+ */
9
+
10
+ @objc(NativeBiometric)
11
+ public class NativeBiometric: CAPPlugin {
12
+
13
+ struct Credentials {
14
+ var username: String
15
+ var password: String
16
+ }
17
+
18
+ enum KeychainError: Error {
19
+ case noPassword
20
+ case unexpectedPasswordData
21
+ case duplicateItem
22
+ case unhandledError(status: OSStatus)
23
+ }
24
+
25
+ typealias JSObject = [String: Any]
26
+
27
+ @objc func isAvailable(_ call: CAPPluginCall) {
28
+ let context = LAContext()
29
+ var error: NSError?
30
+ var obj = JSObject()
31
+
32
+ obj["isAvailable"] = false
33
+ obj["biometryType"] = 0
34
+
35
+ let useFallback = call.getBool("useFallback", false)
36
+ let policy = useFallback ? LAPolicy.deviceOwnerAuthentication : LAPolicy.deviceOwnerAuthenticationWithBiometrics
37
+
38
+ if context.canEvaluatePolicy(policy, error: &error) {
39
+ switch context.biometryType {
40
+ case .touchID:
41
+ obj["biometryType"] = 1
42
+ case .faceID:
43
+ obj["biometryType"] = 2
44
+ default:
45
+ obj["biomertryType"] = 0
46
+ }
47
+
48
+ obj["isAvailable"] = true
49
+ call.resolve(obj)
50
+ } else {
51
+ guard let authError = error else {
52
+ obj["errorCode"] = 0
53
+ call.resolve(obj)
54
+ return
55
+ }
56
+ var errorCode = 0
57
+ switch authError.code {
58
+ case LAError.biometryNotAvailable.rawValue:
59
+ errorCode = 1
60
+
61
+ case LAError.biometryLockout.rawValue:
62
+ errorCode = 2 // "Authentication could not continue because the user has been locked out of biometric authentication, due to failing authentication too many times."
63
+
64
+ case LAError.biometryNotEnrolled.rawValue:
65
+ errorCode = 3// message = "Authentication could not start because the user has not enrolled in biometric authentication."
66
+
67
+ default:
68
+ errorCode = 0 // "Did not find error code on LAError object"
69
+ }
70
+ obj["errorCode"] = errorCode
71
+ call.resolve(obj)
72
+ }
73
+
74
+ }
75
+
76
+ @objc func verifyIdentity(_ call: CAPPluginCall) {
77
+ let context = LAContext()
78
+ var canEvaluateError: NSError?
79
+
80
+ let useFallback = call.getBool("useFallback", false)
81
+ context.localizedFallbackTitle = useFallback ? nil : ""
82
+
83
+ let policy = useFallback ? LAPolicy.deviceOwnerAuthentication : LAPolicy.deviceOwnerAuthenticationWithBiometrics
84
+
85
+ if context.canEvaluatePolicy(policy, error: &canEvaluateError) {
86
+
87
+ let reason = call.getString("reason") ?? "For biometric authentication"
88
+
89
+ context.evaluatePolicy(policy, localizedReason: reason) { (success, evaluateError) in
90
+
91
+ if success {
92
+ call.resolve()
93
+ } else {
94
+ var errorCode = "0"
95
+ guard let error = evaluateError
96
+ else {
97
+ call.reject("Biometrics Error", "0")
98
+ return
99
+ }
100
+
101
+ switch error._code {
102
+
103
+ case LAError.authenticationFailed.rawValue:
104
+ errorCode = "10"
105
+
106
+ case LAError.appCancel.rawValue:
107
+ errorCode = "11"
108
+
109
+ case LAError.invalidContext.rawValue:
110
+ errorCode = "12"
111
+
112
+ case LAError.notInteractive.rawValue:
113
+ errorCode = "13"
114
+
115
+ case LAError.passcodeNotSet.rawValue:
116
+ errorCode = "14"
117
+
118
+ case LAError.systemCancel.rawValue:
119
+ errorCode = "15"
120
+
121
+ case LAError.userCancel.rawValue:
122
+ errorCode = "16"
123
+
124
+ case LAError.userFallback.rawValue:
125
+ errorCode = "17"
126
+
127
+ case LAError.biometryNotAvailable.rawValue:
128
+ errorCode = "1"
129
+
130
+ case LAError.biometryLockout.rawValue:
131
+ errorCode = "2" // "Authentication could not continue because the user has been locked out of biometric authentication, due to failing authentication too many times."
132
+
133
+ case LAError.biometryNotEnrolled.rawValue:
134
+ errorCode = "3" // message = "Authentication could not start because the user has not enrolled in biometric authentication."
135
+
136
+ default:
137
+ errorCode = "0" // Biometrics unavailable
138
+ }
139
+ call.reject(error.localizedDescription, errorCode, error )
140
+ }
141
+
142
+ }
143
+
144
+ } else {
145
+ call.reject("Authentication not available")
146
+ }
147
+ }
148
+
149
+ @objc func getCredentials(_ call: CAPPluginCall) {
150
+ guard let server = call.getString("server") else {
151
+ call.reject("No server name was provided")
152
+ return
153
+ }
154
+ do {
155
+ let credentials = try getCredentialsFromKeychain(server)
156
+ var obj = JSObject()
157
+ obj["username"] = credentials.username
158
+ obj["password"] = credentials.password
159
+ call.resolve(obj)
160
+ } catch {
161
+ call.reject(error.localizedDescription)
162
+ }
163
+ }
164
+
165
+ @objc func setCredentials(_ call: CAPPluginCall) {
166
+
167
+ guard let server = call.getString("server"), let username = call.getString("username"), let password = call.getString("password") else {
168
+ call.reject("Missing properties")
169
+ return
170
+ }
171
+
172
+ let credentials = Credentials(username: username, password: password)
173
+
174
+ do {
175
+ try storeCredentialsInKeychain(credentials, server)
176
+ call.resolve()
177
+ } catch KeychainError.duplicateItem {
178
+ do {
179
+ try updateCredentialsInKeychain(credentials, server)
180
+ call.resolve()
181
+ } catch {
182
+ call.reject(error.localizedDescription)
183
+ }
184
+ } catch {
185
+ call.reject(error.localizedDescription)
186
+ }
187
+ }
188
+
189
+ @objc func deleteCredentials(_ call: CAPPluginCall) {
190
+ guard let server = call.getString("server") else {
191
+ call.reject("No server name was provided")
192
+ return
193
+ }
194
+
195
+ do {
196
+ try deleteCredentialsFromKeychain(server)
197
+ call.resolve()
198
+ } catch {
199
+ call.reject(error.localizedDescription)
200
+ }
201
+ }
202
+
203
+ // Store user Credentials in Keychain
204
+ func storeCredentialsInKeychain(_ credentials: Credentials, _ server: String) throws {
205
+ let query: [String: Any] = [kSecClass as String: kSecClassInternetPassword,
206
+ kSecAttrAccount as String: credentials.username,
207
+ kSecAttrServer as String: server,
208
+ kSecValueData as String: credentials.password.data(using: .utf8)!]
209
+
210
+ let status = SecItemAdd(query as CFDictionary, nil)
211
+
212
+ guard status != errSecDuplicateItem else { throw KeychainError.duplicateItem }
213
+ guard status == errSecSuccess else { throw KeychainError.unhandledError(status: status) }
214
+ }
215
+
216
+ // Update user Credentials in Keychain
217
+ func updateCredentialsInKeychain(_ credentials: Credentials, _ server: String) throws {
218
+ let query: [String: Any] = [kSecClass as String: kSecClassInternetPassword,
219
+ kSecAttrServer as String: server]
220
+
221
+ let account = credentials.username
222
+ let password = credentials.password.data(using: String.Encoding.utf8)!
223
+ let attributes: [String: Any] = [kSecAttrAccount as String: account,
224
+ kSecValueData as String: password]
225
+
226
+ let status = SecItemUpdate(query as CFDictionary, attributes as CFDictionary)
227
+ guard status != errSecItemNotFound else { throw KeychainError.noPassword }
228
+ guard status == errSecSuccess else { throw KeychainError.unhandledError(status: status) }
229
+ }
230
+
231
+ // Get user Credentials from Keychain
232
+ func getCredentialsFromKeychain(_ server: String) throws -> Credentials {
233
+ let query: [String: Any] = [kSecClass as String: kSecClassInternetPassword,
234
+ kSecAttrServer as String: server,
235
+ kSecMatchLimit as String: kSecMatchLimitOne,
236
+ kSecReturnAttributes as String: true,
237
+ kSecReturnData as String: true]
238
+
239
+ var item: CFTypeRef?
240
+ let status = SecItemCopyMatching(query as CFDictionary, &item)
241
+ guard status != errSecItemNotFound else { throw KeychainError.noPassword }
242
+ guard status == errSecSuccess else { throw KeychainError.unhandledError(status: status) }
243
+
244
+ guard let existingItem = item as? [String: Any],
245
+ let passwordData = existingItem[kSecValueData as String] as? Data,
246
+ let password = String(data: passwordData, encoding: .utf8),
247
+ let username = existingItem[kSecAttrAccount as String] as? String
248
+ else {
249
+ throw KeychainError.unexpectedPasswordData
250
+ }
251
+
252
+ let credentials = Credentials(username: username, password: password)
253
+ return credentials
254
+ }
255
+
256
+ // Delete user Credentials from Keychain
257
+ func deleteCredentialsFromKeychain(_ server: String)throws {
258
+ let query: [String: Any] = [kSecClass as String: kSecClassInternetPassword,
259
+ kSecAttrServer as String: server]
260
+
261
+ let status = SecItemDelete(query as CFDictionary)
262
+ guard status == errSecSuccess || status == errSecItemNotFound else { throw KeychainError.unhandledError(status: status) }
263
+ }
264
+ }