├── .gitignore
├── .travis.yml
├── LICENSE
├── README.md
├── demo
├── app
│ ├── App_Resources
│ │ ├── Android
│ │ │ ├── app.gradle
│ │ │ └── src
│ │ │ │ └── main
│ │ │ │ ├── AndroidManifest.xml
│ │ │ │ └── res
│ │ │ │ ├── drawable-hdpi
│ │ │ │ ├── background.png
│ │ │ │ ├── icon.png
│ │ │ │ └── logo.png
│ │ │ │ ├── drawable-ldpi
│ │ │ │ ├── background.png
│ │ │ │ ├── icon.png
│ │ │ │ └── logo.png
│ │ │ │ ├── drawable-mdpi
│ │ │ │ ├── background.png
│ │ │ │ ├── icon.png
│ │ │ │ └── logo.png
│ │ │ │ ├── drawable-nodpi
│ │ │ │ └── splash_screen.xml
│ │ │ │ ├── drawable-xhdpi
│ │ │ │ ├── background.png
│ │ │ │ ├── icon.png
│ │ │ │ └── logo.png
│ │ │ │ ├── drawable-xxhdpi
│ │ │ │ ├── background.png
│ │ │ │ ├── icon.png
│ │ │ │ └── logo.png
│ │ │ │ ├── drawable-xxxhdpi
│ │ │ │ ├── background.png
│ │ │ │ ├── icon.png
│ │ │ │ └── logo.png
│ │ │ │ ├── values-v21
│ │ │ │ ├── colors.xml
│ │ │ │ └── styles.xml
│ │ │ │ └── values
│ │ │ │ ├── colors.xml
│ │ │ │ ├── strings.xml
│ │ │ │ └── styles.xml
│ │ └── iOS
│ │ │ ├── Assets.xcassets
│ │ │ ├── AppIcon.appiconset
│ │ │ │ ├── Contents.json
│ │ │ │ ├── icon-1024.png
│ │ │ │ ├── icon-20.png
│ │ │ │ ├── icon-20@2x.png
│ │ │ │ ├── icon-20@3x.png
│ │ │ │ ├── icon-29.png
│ │ │ │ ├── icon-29@2x.png
│ │ │ │ ├── icon-29@3x.png
│ │ │ │ ├── icon-40.png
│ │ │ │ ├── icon-40@2x.png
│ │ │ │ ├── icon-40@3x.png
│ │ │ │ ├── icon-60@2x.png
│ │ │ │ ├── icon-60@3x.png
│ │ │ │ ├── icon-76.png
│ │ │ │ ├── icon-76@2x.png
│ │ │ │ └── icon-83.5@2x.png
│ │ │ ├── Contents.json
│ │ │ ├── LaunchImage.launchimage
│ │ │ │ ├── Contents.json
│ │ │ │ ├── Default-1125h.png
│ │ │ │ ├── Default-568h@2x.png
│ │ │ │ ├── Default-667h@2x.png
│ │ │ │ ├── Default-736h@3x.png
│ │ │ │ ├── Default-Landscape-X.png
│ │ │ │ ├── Default-Landscape-XR.png
│ │ │ │ ├── Default-Landscape-XS-Max.png
│ │ │ │ ├── Default-Landscape.png
│ │ │ │ ├── Default-Landscape@2x.png
│ │ │ │ ├── Default-Landscape@3x.png
│ │ │ │ ├── Default-Portrait-XR.png
│ │ │ │ ├── Default-Portrait-XS-Max.png
│ │ │ │ ├── Default-Portrait.png
│ │ │ │ ├── Default-Portrait@2x.png
│ │ │ │ ├── Default.png
│ │ │ │ └── Default@2x.png
│ │ │ ├── LaunchScreen.AspectFill.imageset
│ │ │ │ ├── Contents.json
│ │ │ │ ├── LaunchScreen-AspectFill.png
│ │ │ │ ├── LaunchScreen-AspectFill@2x.png
│ │ │ │ └── LaunchScreen-AspectFill@3x.png
│ │ │ └── LaunchScreen.Center.imageset
│ │ │ │ ├── Contents.json
│ │ │ │ ├── LaunchScreen-Center.png
│ │ │ │ ├── LaunchScreen-Center@2x.png
│ │ │ │ └── LaunchScreen-Center@3x.png
│ │ │ ├── Info.plist
│ │ │ ├── LaunchScreen.storyboard
│ │ │ └── build.xcconfig
│ ├── app-root.xml
│ ├── app.css
│ ├── app.ts
│ ├── main-page.ts
│ ├── main-page.xml
│ ├── main-view-model.ts
│ ├── package.json
│ ├── res
│ │ └── telerik-logo.png
│ ├── tests
│ │ └── tests.js
│ └── tsconfig.json
├── karma.conf.js
├── nsconfig.json
├── package.json
├── references.d.ts
├── tsconfig.json
├── tsconfig.tns.json
└── webpack.config.js
├── media
├── fingerprint.png
├── ios-demo-01.png
├── ios-demo-02.png
├── ios-demo-03.png
├── ios-demo-04.png
└── ios-demo-05.png
├── publish
├── pack.sh
├── package-lock.json
├── package.json
└── publish.sh
├── src
├── .npmignore
├── fingerprint-auth.android.ts
├── fingerprint-auth.common.ts
├── fingerprint-auth.ios.ts
├── index.d.ts
├── package.json
├── platforms
│ ├── android
│ │ ├── AndroidManifest.xml
│ │ └── include.gradle
│ └── ios
│ │ └── Info.plist
├── references.d.ts
└── tsconfig.json
└── tslint.json
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea
2 | .vscode
3 | .DS_Store
4 | *.js
5 | *.log
6 | *.map
7 | *.tgz
8 | *.aar
9 | !src/angular/*.js
10 | !demo/karma.conf.js
11 | !demo/app/tests/*.js
12 | !demo/webpack.config.js
13 | demo/*.d.ts
14 | !demo/references.d.ts
15 | src/*.d.ts
16 | !src/index.d.ts
17 | !src/references.d.ts
18 | demo/package-lock.json
19 | demo/lib
20 | demo/platforms
21 | node_modules
22 | demo/hooks/
23 | publish/package/
24 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | android:
2 | components:
3 | - tools
4 | - platform-tools
5 | - build-tools-28.0.3
6 | - android-28
7 | - extra-android-m2repository
8 | - sys-img-armeabi-v7a-android-21
9 |
10 | before_install:
11 | - sudo pip install --upgrade pip
12 | - sudo pip install six
13 |
14 | before_cache:
15 | - rm -f $HOME/.gradle/caches/modules-2/modules-2.lock
16 |
17 | cache:
18 | directories:
19 | - .nvm
20 | - $HOME/.gradle/caches/
21 | - $HOME/.gradle/wrapper/
22 |
23 | install:
24 | - echo no | npm install -g nativescript@6
25 | - tns usage-reporting disable
26 | - tns error-reporting disable
27 | - npm install
28 | - cd src
29 | - npm run setup
30 |
31 | script:
32 |
33 |
34 | matrix:
35 | include:
36 | - stage: "Lint"
37 | language: node_js
38 | os: linux
39 | node_js: "10"
40 | script: "npm run ci.tslint"
41 | - stage: "WebPack"
42 | os: osx
43 | env:
44 | - Webpack="iOS"
45 | osx_image: xcode11.2
46 | language: node_js
47 | node_js: "10"
48 | jdk: oraclejdk8
49 | script: pod repo update && cd ../demo && travis_wait travis_retry tns build ios --bundle
50 | - language: android
51 | os: linux
52 | env:
53 | - Webpack="Android"
54 | jdk: oraclejdk8
55 | before_install: nvm install 10
56 | script: cd ../demo && travis_wait travis_retry tns build android --bundle
57 | - stage: "Build"
58 | env:
59 | - BuildAndroid="28"
60 | language: android
61 | os: linux
62 | jdk: oraclejdk8
63 | before_install: nvm install 10
64 | script:
65 | - cd ../demo && travis_wait travis_retry tns build android
66 | - os: osx
67 | env:
68 | - BuildiOS="12"
69 | - Xcode="11.0"
70 | osx_image: xcode11.2
71 | language: node_js
72 | node_js: "10"
73 | jdk: oraclejdk8
74 | script:
75 | - pod repo update && cd ../demo && travis_wait travis_retry tns build ios
76 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright 2015 - Present, Eddy Verbruggen
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # NativeScript Fingerprint Authentication
2 |
3 | > Also works with Face ID on iPhones 🚀
4 |
5 | [![Build Status][build-status]][build-url]
6 | [![NPM version][npm-image]][npm-url]
7 | [![Downloads][downloads-image]][npm-url]
8 | [![Twitter Follow][twitter-image]][twitter-url]
9 |
10 | [build-status]:https://travis-ci.org/EddyVerbruggen/nativescript-fingerprint-auth.svg?branch=master
11 | [build-url]:https://travis-ci.org/EddyVerbruggen/nativescript-fingerprint-auth
12 | [npm-image]:http://img.shields.io/npm/v/nativescript-fingerprint-auth.svg
13 | [npm-url]:https://npmjs.org/package/nativescript-fingerprint-auth
14 | [downloads-image]:http://img.shields.io/npm/dm/nativescript-fingerprint-auth.svg
15 | [twitter-image]:https://img.shields.io/twitter/follow/eddyverbruggen.svg?style=social&label=Follow%20me
16 | [twitter-url]:https://twitter.com/eddyverbruggen
17 |
18 | > ⚠️ Looking for NativeScript 7 compatibilty? Go to [the NativeScript/plugins repo](https://github.com/NativeScript/plugins/tree/master/packages/fingerprint-auth).
19 |
20 |
21 |
22 | ## Installation
23 | From the command prompt go to your app's root folder and execute:
24 | ```
25 | tns plugin add nativescript-fingerprint-auth
26 | ```
27 |
28 | Then open `App_Resources/Android/AndroidManifest.xml` and look for `minSdkVersion`.
29 | If that's set to a version less than 23, add this `overrideLibrary` line:
30 |
31 | ```xml
32 |
36 | ```
37 |
38 | ## Demo
39 | If you want a quickstart, [check out the demo app](https://github.com/EddyVerbruggen/nativescript-fingerprint-auth/tree/master/demo). Run it locally using these commands:
40 |
41 | ```bash
42 | git clone https://github.com/EddyVerbruggen/nativescript-fingerprint-auth
43 | cd nativescript-fingerprint-auth/src
44 | npm run demo.android # or demo.ios
45 | ```
46 |
47 |
48 |
49 | ## API
50 | Want a nicer guide than these raw code samples? Read [Nic Raboy's blog post about this plugin](https://www.thepolyglotdeveloper.com/2016/03/add-touch-id-authentication-support-to-your-nativescript-app/).
51 |
52 | ### `available`
53 |
54 | #### JavaScript
55 | ```js
56 | var fingerprintAuthPlugin = require("nativescript-fingerprint-auth");
57 | var fingerprintAuth = new fingerprintAuthPlugin.FingerprintAuth();
58 |
59 | fingerprintAuth.available().then(
60 | function(avail) {
61 | console.log("Available? " + avail);
62 | }
63 | )
64 | ```
65 |
66 | #### TypeScript
67 |
68 | ```typescript
69 | import { FingerprintAuth, BiometricIDAvailableResult } from "nativescript-fingerprint-auth";
70 |
71 | class MyClass {
72 | private fingerprintAuth: FingerprintAuth;
73 |
74 | constructor() {
75 | this.fingerprintAuth = new FingerprintAuth();
76 | }
77 |
78 | this.fingerprintAuth.available().then((result: BiometricIDAvailableResult) => {
79 | console.log(`Biometric ID available? ${result.any}`);
80 | console.log(`Touch? ${result.touch}`);
81 | console.log(`Face? ${result.face}`);
82 | });
83 | }
84 | ```
85 |
86 | ### `verifyFingerprint`
87 | Note that on the iOS simulator this will just `resolve()`.
88 |
89 | ```typescript
90 | fingerprintAuth.verifyFingerprint(
91 | {
92 | title: 'Android title', // optional title (used only on Android)
93 | message: 'Scan yer finger', // optional (used on both platforms) - for FaceID on iOS see the notes about NSFaceIDUsageDescription
94 | authenticationValidityDuration: 10, // optional (used on Android, default 5)
95 | useCustomAndroidUI: false // set to true to use a different authentication screen (see below)
96 | })
97 | .then((enteredPassword?: string) => {
98 | if (enteredPassword === undefined) {
99 | console.log("Biometric ID OK")
100 | } else {
101 | // compare enteredPassword to the one the user previously configured for your app (which is not the users system password!)
102 | }
103 | })
104 | .catch(err => console.log(`Biometric ID NOT OK: ${JSON.stringify(err)}`));
105 | ```
106 |
107 | #### A nicer UX/UI on Android (`useCustomAndroidUI: true`)
108 | The default authentication screen on Android is a standalone screen that (depending on the exact Android version) looks kinda 'uninteresting'.
109 | So with version 6.0.0 this plugin added the ability to override the default screen and offer an iOS popover style which you can activate by passing in `useCustomAndroidUI: true` in the function above.
110 |
111 | One important thing to realize is that the 'use password' option in this dialog doesn't verify the entered password against
112 | the system password. It must be used to compare the entered password with an app-specific password the user previously configured.
113 |
114 | The password fallback can be disabled by overriding the default `use_password` text to a blank string (see optional change below for details on how to do this).
115 |
116 | ##### Optional change
117 | If you want to override the default texts of this popover screen, then drop a file [`strings.xml`](https://github.com/EddyVerbruggen/nativescript-fingerprint-auth/blob/5a14f96f7e752953df506401588b5694e3ab6444/demo/app/App_Resources/Android/src/main/res/values/strings.xml) in your project and override the properties you like. See the demo app for an example.
118 |
119 | ##### ⚠️ Important note when using NativeScript < 5.4.0
120 | **Use plugin version < 7.0.0 to be able to use this feature with NativeScript < 5.4.0**
121 |
122 | > Skip this section if you're on NativeScript 5.4.0 or newer because it's all handled automatically!
123 |
124 | To be able to use this screen, a change to `App_Resources/Android/AndroidManifest.xml` is required as our NativeScript activity needs to extend AppCompatActivity (note that in the future this may become the default for NativeScript apps).
125 |
126 | To do so, open the file and replace ` {
163 | console.log("Fingerprint was OK");
164 | },
165 | error => {
166 | // when error.code === -3, the user pressed the button labeled with your fallbackMessage
167 | console.log("Fingerprint NOT OK. Error code: " + error.code + ". Error message: " + error.message);
168 | }
169 | );
170 | ```
171 |
172 | ## Face ID (iOS)
173 | iOS 11 added support for Face ID and was first supported by the iPhone X.
174 | The developer needs to provide a value for `NSFaceIDUsageDescription`, otherwise your app may crash.
175 |
176 | You can provide this value (the reason for using Face ID) by adding something like this to `app/App_Resources/ios/Info.plist`:
177 |
178 | ```xml
179 | NSFaceIDUsageDescription
180 | For easy authentication with our app.
181 | ```
182 |
183 | ## Security++ (iOS)
184 | Since iOS9 it's possible to check whether or not the list of enrolled fingerprints changed since
185 | the last time you checked it. It's recommended you add this check so you can counter hacker attacks
186 | to your app. See [this article](https://godpraksis.no/2016/03/fingerprint-trojan/) for more details.
187 |
188 | So instead of checking the fingerprint after `available` add another check.
189 | In case `didFingerprintDatabaseChange` returns `true` you probably want to re-authenticate your user
190 | before accepting valid fingerprints again.
191 |
192 | ```typescript
193 | fingerprintAuth.available().then(avail => {
194 | if (!avail) {
195 | return;
196 | }
197 | fingerprintAuth.didFingerprintDatabaseChange().then(changed => {
198 | if (changed) {
199 | // re-auth the user by asking for his credentials before allowing a fingerprint scan again
200 | } else {
201 | // call the fingerprint scanner
202 | }
203 | });
204 | });
205 | ```
206 |
207 | ## Changelog
208 | - 6.2.0 [Fixed a potential bypass on iOS](https://github.com/EddyVerbruggen/nativescript-fingerprint-auth/issues/41).
209 | - 6.1.0 [Fixed potentioal bypasses on Android](https://github.com/EddyVerbruggen/nativescript-fingerprint-auth/milestone/8?closed=1).
210 | - 6.0.3 [Android interfered with other plugins' Intents](https://github.com/EddyVerbruggen/nativescript-fingerprint-auth/pull/28).
211 | - 6.0.2 [Plugin not working correctly on iOS production builds / TestFlight](https://github.com/EddyVerbruggen/nativescript-fingerprint-auth/issues/27).
212 | - 6.0.1 Fixed a compatibility issues with NativeScript 3.4.
213 | - 6.0.0 Allow custom UI on Android.
214 | - 5.0.0 Better `Face ID` support. Breaking change, see the API for `available`.
215 | - 4.0.1 Aligned with [the official NativeScript plugin seed](https://github.com/NativeScript/nativescript-plugin-seed). Requires NativeScript 3.0.0+. Thanks, @angeltsvetkov!
216 | - 4.0.0 Converted to TypeScript. Changed the error response type of `verifyFingerprintWithCustomFallback`.
217 | - 3.0.0 Android support added. Renamed `nativescript-touchid` to `nativescript-fingerprint-auth` (sorry for any inconvenience!).
218 | - 2.1.1 Xcode 8 compatibility - requires NativeScript 2.3.0+.
219 | - 2.1.0 Added `didFingerprintDatabaseChange` for enhanced security.
220 | - 2.0.0 Added `verifyFingerprintWithCustomFallback`, `verifyFingerprint` now falls back to the passcode.
221 | - 1.2.0 You can now use the built-in passcode interface as fallback.
222 | - 1.1.1 Added TypeScript definitions.
223 | - 1.1.0 Added Android platform which will always return false for `touchid.available`.
224 |
--------------------------------------------------------------------------------
/demo/app/App_Resources/Android/app.gradle:
--------------------------------------------------------------------------------
1 | // Add your native dependencies here:
2 |
3 | // Uncomment to add recyclerview-v7 dependency
4 | //dependencies {
5 | // implementation 'com.android.support:recyclerview-v7:+'
6 | //}
7 |
8 | // If you want to add something to be applied before applying plugins' include.gradle files
9 | // e.g. project.ext.googlePlayServicesVersion = "15.0.1"
10 | // create a file named before-plugins.gradle in the current directory and place it there
11 |
12 | android {
13 | defaultConfig {
14 | minSdkVersion 17
15 | generatedDensities = []
16 | }
17 | aaptOptions {
18 | additionalParameters "--no-version-vectors"
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/demo/app/App_Resources/Android/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/demo/app/App_Resources/Android/src/main/res/drawable-hdpi/background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EddyVerbruggen/nativescript-fingerprint-auth/27461046c4479c0cd4d775fb72f5783e67742c39/demo/app/App_Resources/Android/src/main/res/drawable-hdpi/background.png
--------------------------------------------------------------------------------
/demo/app/App_Resources/Android/src/main/res/drawable-hdpi/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EddyVerbruggen/nativescript-fingerprint-auth/27461046c4479c0cd4d775fb72f5783e67742c39/demo/app/App_Resources/Android/src/main/res/drawable-hdpi/icon.png
--------------------------------------------------------------------------------
/demo/app/App_Resources/Android/src/main/res/drawable-hdpi/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EddyVerbruggen/nativescript-fingerprint-auth/27461046c4479c0cd4d775fb72f5783e67742c39/demo/app/App_Resources/Android/src/main/res/drawable-hdpi/logo.png
--------------------------------------------------------------------------------
/demo/app/App_Resources/Android/src/main/res/drawable-ldpi/background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EddyVerbruggen/nativescript-fingerprint-auth/27461046c4479c0cd4d775fb72f5783e67742c39/demo/app/App_Resources/Android/src/main/res/drawable-ldpi/background.png
--------------------------------------------------------------------------------
/demo/app/App_Resources/Android/src/main/res/drawable-ldpi/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EddyVerbruggen/nativescript-fingerprint-auth/27461046c4479c0cd4d775fb72f5783e67742c39/demo/app/App_Resources/Android/src/main/res/drawable-ldpi/icon.png
--------------------------------------------------------------------------------
/demo/app/App_Resources/Android/src/main/res/drawable-ldpi/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EddyVerbruggen/nativescript-fingerprint-auth/27461046c4479c0cd4d775fb72f5783e67742c39/demo/app/App_Resources/Android/src/main/res/drawable-ldpi/logo.png
--------------------------------------------------------------------------------
/demo/app/App_Resources/Android/src/main/res/drawable-mdpi/background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EddyVerbruggen/nativescript-fingerprint-auth/27461046c4479c0cd4d775fb72f5783e67742c39/demo/app/App_Resources/Android/src/main/res/drawable-mdpi/background.png
--------------------------------------------------------------------------------
/demo/app/App_Resources/Android/src/main/res/drawable-mdpi/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EddyVerbruggen/nativescript-fingerprint-auth/27461046c4479c0cd4d775fb72f5783e67742c39/demo/app/App_Resources/Android/src/main/res/drawable-mdpi/icon.png
--------------------------------------------------------------------------------
/demo/app/App_Resources/Android/src/main/res/drawable-mdpi/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EddyVerbruggen/nativescript-fingerprint-auth/27461046c4479c0cd4d775fb72f5783e67742c39/demo/app/App_Resources/Android/src/main/res/drawable-mdpi/logo.png
--------------------------------------------------------------------------------
/demo/app/App_Resources/Android/src/main/res/drawable-nodpi/splash_screen.xml:
--------------------------------------------------------------------------------
1 |
2 | -
3 |
4 |
5 | -
6 |
7 |
8 |
--------------------------------------------------------------------------------
/demo/app/App_Resources/Android/src/main/res/drawable-xhdpi/background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EddyVerbruggen/nativescript-fingerprint-auth/27461046c4479c0cd4d775fb72f5783e67742c39/demo/app/App_Resources/Android/src/main/res/drawable-xhdpi/background.png
--------------------------------------------------------------------------------
/demo/app/App_Resources/Android/src/main/res/drawable-xhdpi/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EddyVerbruggen/nativescript-fingerprint-auth/27461046c4479c0cd4d775fb72f5783e67742c39/demo/app/App_Resources/Android/src/main/res/drawable-xhdpi/icon.png
--------------------------------------------------------------------------------
/demo/app/App_Resources/Android/src/main/res/drawable-xhdpi/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EddyVerbruggen/nativescript-fingerprint-auth/27461046c4479c0cd4d775fb72f5783e67742c39/demo/app/App_Resources/Android/src/main/res/drawable-xhdpi/logo.png
--------------------------------------------------------------------------------
/demo/app/App_Resources/Android/src/main/res/drawable-xxhdpi/background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EddyVerbruggen/nativescript-fingerprint-auth/27461046c4479c0cd4d775fb72f5783e67742c39/demo/app/App_Resources/Android/src/main/res/drawable-xxhdpi/background.png
--------------------------------------------------------------------------------
/demo/app/App_Resources/Android/src/main/res/drawable-xxhdpi/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EddyVerbruggen/nativescript-fingerprint-auth/27461046c4479c0cd4d775fb72f5783e67742c39/demo/app/App_Resources/Android/src/main/res/drawable-xxhdpi/icon.png
--------------------------------------------------------------------------------
/demo/app/App_Resources/Android/src/main/res/drawable-xxhdpi/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EddyVerbruggen/nativescript-fingerprint-auth/27461046c4479c0cd4d775fb72f5783e67742c39/demo/app/App_Resources/Android/src/main/res/drawable-xxhdpi/logo.png
--------------------------------------------------------------------------------
/demo/app/App_Resources/Android/src/main/res/drawable-xxxhdpi/background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EddyVerbruggen/nativescript-fingerprint-auth/27461046c4479c0cd4d775fb72f5783e67742c39/demo/app/App_Resources/Android/src/main/res/drawable-xxxhdpi/background.png
--------------------------------------------------------------------------------
/demo/app/App_Resources/Android/src/main/res/drawable-xxxhdpi/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EddyVerbruggen/nativescript-fingerprint-auth/27461046c4479c0cd4d775fb72f5783e67742c39/demo/app/App_Resources/Android/src/main/res/drawable-xxxhdpi/icon.png
--------------------------------------------------------------------------------
/demo/app/App_Resources/Android/src/main/res/drawable-xxxhdpi/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EddyVerbruggen/nativescript-fingerprint-auth/27461046c4479c0cd4d775fb72f5783e67742c39/demo/app/App_Resources/Android/src/main/res/drawable-xxxhdpi/logo.png
--------------------------------------------------------------------------------
/demo/app/App_Resources/Android/src/main/res/values-v21/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #3d5afe
4 |
--------------------------------------------------------------------------------
/demo/app/App_Resources/Android/src/main/res/values-v21/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
9 |
10 |
11 |
14 |
15 |
16 |
19 |
20 |
23 |
--------------------------------------------------------------------------------
/demo/app/App_Resources/Android/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #F5F5F5
4 | #757575
5 | #33B5E5
6 | #272734
7 |
--------------------------------------------------------------------------------
/demo/app/App_Resources/Android/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | Fingerprint
3 | Fingerprint
4 |
5 | Cancel
6 | Use password
7 | OK
8 | Enter your password to continue
9 | A new fingerprint was added to this device, so your password is required.
10 |
11 | Use fingerprint in the future
12 | use_fingerprint_to_authenticate_key
13 |
14 | Touch da sensor
15 |
16 |
17 | Security -> Fingerprint\' to set up a fingerprint\"]]>
18 | Go to \'Settings -> Security -> Fingerprint\' and register at least one fingerprint
19 | Fingerprint not initialised
20 | Fingerprint not available
21 | Fingerprint not recognized
22 | Password can\'t be empty
23 |
--------------------------------------------------------------------------------
/demo/app/App_Resources/Android/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
18 |
19 |
21 |
22 |
23 |
31 |
32 |
34 |
35 |
36 |
42 |
43 |
45 |
46 |
--------------------------------------------------------------------------------
/demo/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "size" : "20x20",
5 | "idiom" : "iphone",
6 | "filename" : "icon-20@2x.png",
7 | "scale" : "2x"
8 | },
9 | {
10 | "size" : "20x20",
11 | "idiom" : "iphone",
12 | "filename" : "icon-20@3x.png",
13 | "scale" : "3x"
14 | },
15 | {
16 | "size" : "29x29",
17 | "idiom" : "iphone",
18 | "filename" : "icon-29.png",
19 | "scale" : "1x"
20 | },
21 | {
22 | "size" : "29x29",
23 | "idiom" : "iphone",
24 | "filename" : "icon-29@2x.png",
25 | "scale" : "2x"
26 | },
27 | {
28 | "size" : "29x29",
29 | "idiom" : "iphone",
30 | "filename" : "icon-29@3x.png",
31 | "scale" : "3x"
32 | },
33 | {
34 | "size" : "40x40",
35 | "idiom" : "iphone",
36 | "filename" : "icon-40@2x.png",
37 | "scale" : "2x"
38 | },
39 | {
40 | "size" : "40x40",
41 | "idiom" : "iphone",
42 | "filename" : "icon-40@3x.png",
43 | "scale" : "3x"
44 | },
45 | {
46 | "size" : "60x60",
47 | "idiom" : "iphone",
48 | "filename" : "icon-60@2x.png",
49 | "scale" : "2x"
50 | },
51 | {
52 | "size" : "60x60",
53 | "idiom" : "iphone",
54 | "filename" : "icon-60@3x.png",
55 | "scale" : "3x"
56 | },
57 | {
58 | "size" : "20x20",
59 | "idiom" : "ipad",
60 | "filename" : "icon-20.png",
61 | "scale" : "1x"
62 | },
63 | {
64 | "size" : "20x20",
65 | "idiom" : "ipad",
66 | "filename" : "icon-20@2x.png",
67 | "scale" : "2x"
68 | },
69 | {
70 | "size" : "29x29",
71 | "idiom" : "ipad",
72 | "filename" : "icon-29.png",
73 | "scale" : "1x"
74 | },
75 | {
76 | "size" : "29x29",
77 | "idiom" : "ipad",
78 | "filename" : "icon-29@2x.png",
79 | "scale" : "2x"
80 | },
81 | {
82 | "size" : "40x40",
83 | "idiom" : "ipad",
84 | "filename" : "icon-40.png",
85 | "scale" : "1x"
86 | },
87 | {
88 | "size" : "40x40",
89 | "idiom" : "ipad",
90 | "filename" : "icon-40@2x.png",
91 | "scale" : "2x"
92 | },
93 | {
94 | "size" : "76x76",
95 | "idiom" : "ipad",
96 | "filename" : "icon-76.png",
97 | "scale" : "1x"
98 | },
99 | {
100 | "size" : "76x76",
101 | "idiom" : "ipad",
102 | "filename" : "icon-76@2x.png",
103 | "scale" : "2x"
104 | },
105 | {
106 | "size" : "83.5x83.5",
107 | "idiom" : "ipad",
108 | "filename" : "icon-83.5@2x.png",
109 | "scale" : "2x"
110 | },
111 | {
112 | "size" : "1024x1024",
113 | "idiom" : "ios-marketing",
114 | "filename" : "icon-1024.png",
115 | "scale" : "1x"
116 | }
117 | ],
118 | "info" : {
119 | "version" : 1,
120 | "author" : "xcode"
121 | }
122 | }
--------------------------------------------------------------------------------
/demo/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-1024.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EddyVerbruggen/nativescript-fingerprint-auth/27461046c4479c0cd4d775fb72f5783e67742c39/demo/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-1024.png
--------------------------------------------------------------------------------
/demo/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-20.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EddyVerbruggen/nativescript-fingerprint-auth/27461046c4479c0cd4d775fb72f5783e67742c39/demo/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-20.png
--------------------------------------------------------------------------------
/demo/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-20@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EddyVerbruggen/nativescript-fingerprint-auth/27461046c4479c0cd4d775fb72f5783e67742c39/demo/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-20@2x.png
--------------------------------------------------------------------------------
/demo/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-20@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EddyVerbruggen/nativescript-fingerprint-auth/27461046c4479c0cd4d775fb72f5783e67742c39/demo/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-20@3x.png
--------------------------------------------------------------------------------
/demo/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-29.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EddyVerbruggen/nativescript-fingerprint-auth/27461046c4479c0cd4d775fb72f5783e67742c39/demo/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-29.png
--------------------------------------------------------------------------------
/demo/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-29@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EddyVerbruggen/nativescript-fingerprint-auth/27461046c4479c0cd4d775fb72f5783e67742c39/demo/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-29@2x.png
--------------------------------------------------------------------------------
/demo/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-29@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EddyVerbruggen/nativescript-fingerprint-auth/27461046c4479c0cd4d775fb72f5783e67742c39/demo/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-29@3x.png
--------------------------------------------------------------------------------
/demo/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-40.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EddyVerbruggen/nativescript-fingerprint-auth/27461046c4479c0cd4d775fb72f5783e67742c39/demo/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-40.png
--------------------------------------------------------------------------------
/demo/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-40@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EddyVerbruggen/nativescript-fingerprint-auth/27461046c4479c0cd4d775fb72f5783e67742c39/demo/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-40@2x.png
--------------------------------------------------------------------------------
/demo/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-40@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EddyVerbruggen/nativescript-fingerprint-auth/27461046c4479c0cd4d775fb72f5783e67742c39/demo/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-40@3x.png
--------------------------------------------------------------------------------
/demo/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-60@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EddyVerbruggen/nativescript-fingerprint-auth/27461046c4479c0cd4d775fb72f5783e67742c39/demo/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-60@2x.png
--------------------------------------------------------------------------------
/demo/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-60@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EddyVerbruggen/nativescript-fingerprint-auth/27461046c4479c0cd4d775fb72f5783e67742c39/demo/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-60@3x.png
--------------------------------------------------------------------------------
/demo/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-76.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EddyVerbruggen/nativescript-fingerprint-auth/27461046c4479c0cd4d775fb72f5783e67742c39/demo/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-76.png
--------------------------------------------------------------------------------
/demo/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-76@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EddyVerbruggen/nativescript-fingerprint-auth/27461046c4479c0cd4d775fb72f5783e67742c39/demo/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-76@2x.png
--------------------------------------------------------------------------------
/demo/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-83.5@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EddyVerbruggen/nativescript-fingerprint-auth/27461046c4479c0cd4d775fb72f5783e67742c39/demo/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-83.5@2x.png
--------------------------------------------------------------------------------
/demo/app/App_Resources/iOS/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
--------------------------------------------------------------------------------
/demo/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "extent" : "full-screen",
5 | "idiom" : "iphone",
6 | "subtype" : "2688h",
7 | "filename" : "Default-Portrait-XS-Max.png",
8 | "minimum-system-version" : "12.0",
9 | "orientation" : "portrait",
10 | "scale" : "3x"
11 | },
12 | {
13 | "extent" : "full-screen",
14 | "idiom" : "iphone",
15 | "subtype" : "2688h",
16 | "filename" : "Default-Landscape-XS-Max.png",
17 | "minimum-system-version" : "12.0",
18 | "orientation" : "landscape",
19 | "scale" : "3x"
20 | },
21 | {
22 | "extent" : "full-screen",
23 | "idiom" : "iphone",
24 | "subtype" : "1792h",
25 | "filename" : "Default-Portrait-XR.png",
26 | "minimum-system-version" : "12.0",
27 | "orientation" : "portrait",
28 | "scale" : "2x"
29 | },
30 | {
31 | "extent" : "full-screen",
32 | "idiom" : "iphone",
33 | "subtype" : "1792h",
34 | "filename" : "Default-Landscape-XR.png",
35 | "minimum-system-version" : "12.0",
36 | "orientation" : "landscape",
37 | "scale" : "2x"
38 | },
39 | {
40 | "extent" : "full-screen",
41 | "idiom" : "iphone",
42 | "subtype" : "2436h",
43 | "filename" : "Default-1125h.png",
44 | "minimum-system-version" : "11.0",
45 | "orientation" : "portrait",
46 | "scale" : "3x"
47 | },
48 | {
49 | "extent" : "full-screen",
50 | "idiom" : "iphone",
51 | "subtype" : "2436h",
52 | "filename" : "Default-Landscape-X.png",
53 | "minimum-system-version" : "11.0",
54 | "orientation" : "landscape",
55 | "scale" : "3x"
56 | },
57 | {
58 | "extent" : "full-screen",
59 | "idiom" : "iphone",
60 | "subtype" : "736h",
61 | "filename" : "Default-736h@3x.png",
62 | "minimum-system-version" : "8.0",
63 | "orientation" : "portrait",
64 | "scale" : "3x"
65 | },
66 | {
67 | "extent" : "full-screen",
68 | "idiom" : "iphone",
69 | "subtype" : "736h",
70 | "filename" : "Default-Landscape@3x.png",
71 | "minimum-system-version" : "8.0",
72 | "orientation" : "landscape",
73 | "scale" : "3x"
74 | },
75 | {
76 | "extent" : "full-screen",
77 | "idiom" : "iphone",
78 | "subtype" : "667h",
79 | "filename" : "Default-667h@2x.png",
80 | "minimum-system-version" : "8.0",
81 | "orientation" : "portrait",
82 | "scale" : "2x"
83 | },
84 | {
85 | "orientation" : "portrait",
86 | "idiom" : "iphone",
87 | "filename" : "Default@2x.png",
88 | "extent" : "full-screen",
89 | "minimum-system-version" : "7.0",
90 | "scale" : "2x"
91 | },
92 | {
93 | "extent" : "full-screen",
94 | "idiom" : "iphone",
95 | "subtype" : "retina4",
96 | "filename" : "Default-568h@2x.png",
97 | "minimum-system-version" : "7.0",
98 | "orientation" : "portrait",
99 | "scale" : "2x"
100 | },
101 | {
102 | "orientation" : "portrait",
103 | "idiom" : "ipad",
104 | "filename" : "Default-Portrait.png",
105 | "extent" : "full-screen",
106 | "minimum-system-version" : "7.0",
107 | "scale" : "1x"
108 | },
109 | {
110 | "orientation" : "landscape",
111 | "idiom" : "ipad",
112 | "filename" : "Default-Landscape.png",
113 | "extent" : "full-screen",
114 | "minimum-system-version" : "7.0",
115 | "scale" : "1x"
116 | },
117 | {
118 | "orientation" : "portrait",
119 | "idiom" : "ipad",
120 | "filename" : "Default-Portrait@2x.png",
121 | "extent" : "full-screen",
122 | "minimum-system-version" : "7.0",
123 | "scale" : "2x"
124 | },
125 | {
126 | "orientation" : "landscape",
127 | "idiom" : "ipad",
128 | "filename" : "Default-Landscape@2x.png",
129 | "extent" : "full-screen",
130 | "minimum-system-version" : "7.0",
131 | "scale" : "2x"
132 | },
133 | {
134 | "orientation" : "portrait",
135 | "idiom" : "iphone",
136 | "filename" : "Default.png",
137 | "extent" : "full-screen",
138 | "scale" : "1x"
139 | },
140 | {
141 | "orientation" : "portrait",
142 | "idiom" : "iphone",
143 | "filename" : "Default@2x.png",
144 | "extent" : "full-screen",
145 | "scale" : "2x"
146 | },
147 | {
148 | "orientation" : "portrait",
149 | "idiom" : "iphone",
150 | "filename" : "Default-568h@2x.png",
151 | "extent" : "full-screen",
152 | "subtype" : "retina4",
153 | "scale" : "2x"
154 | },
155 | {
156 | "orientation" : "portrait",
157 | "idiom" : "ipad",
158 | "extent" : "to-status-bar",
159 | "scale" : "1x"
160 | },
161 | {
162 | "orientation" : "portrait",
163 | "idiom" : "ipad",
164 | "filename" : "Default-Portrait.png",
165 | "extent" : "full-screen",
166 | "scale" : "1x"
167 | },
168 | {
169 | "orientation" : "landscape",
170 | "idiom" : "ipad",
171 | "extent" : "to-status-bar",
172 | "scale" : "1x"
173 | },
174 | {
175 | "orientation" : "landscape",
176 | "idiom" : "ipad",
177 | "filename" : "Default-Landscape.png",
178 | "extent" : "full-screen",
179 | "scale" : "1x"
180 | },
181 | {
182 | "orientation" : "portrait",
183 | "idiom" : "ipad",
184 | "extent" : "to-status-bar",
185 | "scale" : "2x"
186 | },
187 | {
188 | "orientation" : "portrait",
189 | "idiom" : "ipad",
190 | "filename" : "Default-Portrait@2x.png",
191 | "extent" : "full-screen",
192 | "scale" : "2x"
193 | },
194 | {
195 | "orientation" : "landscape",
196 | "idiom" : "ipad",
197 | "extent" : "to-status-bar",
198 | "scale" : "2x"
199 | },
200 | {
201 | "orientation" : "landscape",
202 | "idiom" : "ipad",
203 | "filename" : "Default-Landscape@2x.png",
204 | "extent" : "full-screen",
205 | "scale" : "2x"
206 | }
207 | ],
208 | "info" : {
209 | "version" : 1,
210 | "author" : "xcode"
211 | }
212 | }
--------------------------------------------------------------------------------
/demo/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-1125h.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EddyVerbruggen/nativescript-fingerprint-auth/27461046c4479c0cd4d775fb72f5783e67742c39/demo/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-1125h.png
--------------------------------------------------------------------------------
/demo/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-568h@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EddyVerbruggen/nativescript-fingerprint-auth/27461046c4479c0cd4d775fb72f5783e67742c39/demo/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-568h@2x.png
--------------------------------------------------------------------------------
/demo/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-667h@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EddyVerbruggen/nativescript-fingerprint-auth/27461046c4479c0cd4d775fb72f5783e67742c39/demo/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-667h@2x.png
--------------------------------------------------------------------------------
/demo/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-736h@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EddyVerbruggen/nativescript-fingerprint-auth/27461046c4479c0cd4d775fb72f5783e67742c39/demo/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-736h@3x.png
--------------------------------------------------------------------------------
/demo/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-Landscape-X.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EddyVerbruggen/nativescript-fingerprint-auth/27461046c4479c0cd4d775fb72f5783e67742c39/demo/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-Landscape-X.png
--------------------------------------------------------------------------------
/demo/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-Landscape-XR.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EddyVerbruggen/nativescript-fingerprint-auth/27461046c4479c0cd4d775fb72f5783e67742c39/demo/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-Landscape-XR.png
--------------------------------------------------------------------------------
/demo/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-Landscape-XS-Max.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EddyVerbruggen/nativescript-fingerprint-auth/27461046c4479c0cd4d775fb72f5783e67742c39/demo/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-Landscape-XS-Max.png
--------------------------------------------------------------------------------
/demo/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-Landscape.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EddyVerbruggen/nativescript-fingerprint-auth/27461046c4479c0cd4d775fb72f5783e67742c39/demo/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-Landscape.png
--------------------------------------------------------------------------------
/demo/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-Landscape@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EddyVerbruggen/nativescript-fingerprint-auth/27461046c4479c0cd4d775fb72f5783e67742c39/demo/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-Landscape@2x.png
--------------------------------------------------------------------------------
/demo/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-Landscape@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EddyVerbruggen/nativescript-fingerprint-auth/27461046c4479c0cd4d775fb72f5783e67742c39/demo/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-Landscape@3x.png
--------------------------------------------------------------------------------
/demo/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-Portrait-XR.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EddyVerbruggen/nativescript-fingerprint-auth/27461046c4479c0cd4d775fb72f5783e67742c39/demo/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-Portrait-XR.png
--------------------------------------------------------------------------------
/demo/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-Portrait-XS-Max.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EddyVerbruggen/nativescript-fingerprint-auth/27461046c4479c0cd4d775fb72f5783e67742c39/demo/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-Portrait-XS-Max.png
--------------------------------------------------------------------------------
/demo/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-Portrait.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EddyVerbruggen/nativescript-fingerprint-auth/27461046c4479c0cd4d775fb72f5783e67742c39/demo/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-Portrait.png
--------------------------------------------------------------------------------
/demo/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-Portrait@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EddyVerbruggen/nativescript-fingerprint-auth/27461046c4479c0cd4d775fb72f5783e67742c39/demo/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-Portrait@2x.png
--------------------------------------------------------------------------------
/demo/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EddyVerbruggen/nativescript-fingerprint-auth/27461046c4479c0cd4d775fb72f5783e67742c39/demo/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default.png
--------------------------------------------------------------------------------
/demo/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EddyVerbruggen/nativescript-fingerprint-auth/27461046c4479c0cd4d775fb72f5783e67742c39/demo/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default@2x.png
--------------------------------------------------------------------------------
/demo/app/App_Resources/iOS/Assets.xcassets/LaunchScreen.AspectFill.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "LaunchScreen-AspectFill.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "filename" : "LaunchScreen-AspectFill@2x.png",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "universal",
15 | "filename" : "LaunchScreen-AspectFill@3x.png",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "version" : 1,
21 | "author" : "xcode"
22 | }
23 | }
--------------------------------------------------------------------------------
/demo/app/App_Resources/iOS/Assets.xcassets/LaunchScreen.AspectFill.imageset/LaunchScreen-AspectFill.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EddyVerbruggen/nativescript-fingerprint-auth/27461046c4479c0cd4d775fb72f5783e67742c39/demo/app/App_Resources/iOS/Assets.xcassets/LaunchScreen.AspectFill.imageset/LaunchScreen-AspectFill.png
--------------------------------------------------------------------------------
/demo/app/App_Resources/iOS/Assets.xcassets/LaunchScreen.AspectFill.imageset/LaunchScreen-AspectFill@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EddyVerbruggen/nativescript-fingerprint-auth/27461046c4479c0cd4d775fb72f5783e67742c39/demo/app/App_Resources/iOS/Assets.xcassets/LaunchScreen.AspectFill.imageset/LaunchScreen-AspectFill@2x.png
--------------------------------------------------------------------------------
/demo/app/App_Resources/iOS/Assets.xcassets/LaunchScreen.AspectFill.imageset/LaunchScreen-AspectFill@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EddyVerbruggen/nativescript-fingerprint-auth/27461046c4479c0cd4d775fb72f5783e67742c39/demo/app/App_Resources/iOS/Assets.xcassets/LaunchScreen.AspectFill.imageset/LaunchScreen-AspectFill@3x.png
--------------------------------------------------------------------------------
/demo/app/App_Resources/iOS/Assets.xcassets/LaunchScreen.Center.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "LaunchScreen-Center.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "filename" : "LaunchScreen-Center@2x.png",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "universal",
15 | "filename" : "LaunchScreen-Center@3x.png",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "version" : 1,
21 | "author" : "xcode"
22 | }
23 | }
--------------------------------------------------------------------------------
/demo/app/App_Resources/iOS/Assets.xcassets/LaunchScreen.Center.imageset/LaunchScreen-Center.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EddyVerbruggen/nativescript-fingerprint-auth/27461046c4479c0cd4d775fb72f5783e67742c39/demo/app/App_Resources/iOS/Assets.xcassets/LaunchScreen.Center.imageset/LaunchScreen-Center.png
--------------------------------------------------------------------------------
/demo/app/App_Resources/iOS/Assets.xcassets/LaunchScreen.Center.imageset/LaunchScreen-Center@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EddyVerbruggen/nativescript-fingerprint-auth/27461046c4479c0cd4d775fb72f5783e67742c39/demo/app/App_Resources/iOS/Assets.xcassets/LaunchScreen.Center.imageset/LaunchScreen-Center@2x.png
--------------------------------------------------------------------------------
/demo/app/App_Resources/iOS/Assets.xcassets/LaunchScreen.Center.imageset/LaunchScreen-Center@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EddyVerbruggen/nativescript-fingerprint-auth/27461046c4479c0cd4d775fb72f5783e67742c39/demo/app/App_Resources/iOS/Assets.xcassets/LaunchScreen.Center.imageset/LaunchScreen-Center@3x.png
--------------------------------------------------------------------------------
/demo/app/App_Resources/iOS/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleDisplayName
8 | ${PRODUCT_NAME}
9 | CFBundleExecutable
10 | ${EXECUTABLE_NAME}
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | ${PRODUCT_NAME}
15 | CFBundlePackageType
16 | APPL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1.0
23 | LSRequiresIPhoneOS
24 |
25 | UILaunchStoryboardName
26 | LaunchScreen
27 | UIRequiresFullScreen
28 |
29 | UIRequiredDeviceCapabilities
30 |
31 | armv7
32 |
33 | UISupportedInterfaceOrientations
34 |
35 | UIInterfaceOrientationPortrait
36 | UIInterfaceOrientationLandscapeLeft
37 | UIInterfaceOrientationLandscapeRight
38 |
39 | UISupportedInterfaceOrientations~ipad
40 |
41 | UIInterfaceOrientationPortrait
42 | UIInterfaceOrientationPortraitUpsideDown
43 | UIInterfaceOrientationLandscapeLeft
44 | UIInterfaceOrientationLandscapeRight
45 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/demo/app/App_Resources/iOS/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
--------------------------------------------------------------------------------
/demo/app/App_Resources/iOS/build.xcconfig:
--------------------------------------------------------------------------------
1 | // You can add custom settings here
2 | // for example you can uncomment the following line to force distribution code signing
3 | // CODE_SIGN_IDENTITY = iPhone Distribution
4 | // To build for device with XCode 8 you need to specify your development team. More info: https://developer.apple.com/library/prerelease/content/releasenotes/DeveloperTools/RN-Xcode/Introduction.html
5 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
6 | ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;
7 |
--------------------------------------------------------------------------------
/demo/app/app-root.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/demo/app/app.css:
--------------------------------------------------------------------------------
1 | page {
2 | background-color: #F4F4F4;
3 | }
4 |
5 | label {
6 | font-size: 14;
7 | }
8 |
9 | .tab-content {
10 | color: #808080;
11 | padding: 20;
12 | }
13 |
14 | .title {
15 | font-size: 18;
16 | margin: 0 0 10 0;
17 | color: #3c3c3c;
18 | }
19 |
20 | .status {
21 | border-radius: 8;
22 | font-size: 16;
23 | margin: 20;
24 | padding: 18 12;
25 | color: #444444;
26 | background-color: #cccccc;
27 | border-color: #aaaaaa;
28 | border-width: 1px;
29 | }
30 |
31 | button {
32 | background-color: #3598db;
33 | padding: 8 0;
34 | margin: 10;
35 | margin-bottom: 20;
36 | font-size: 16;
37 | border-radius: 4;
38 | }
39 |
40 | .button {
41 | /* don't add this class to 'button' above since it will make 'alert/actionsheet' buttons white as well */
42 | color: #ffffff;
43 | }
--------------------------------------------------------------------------------
/demo/app/app.ts:
--------------------------------------------------------------------------------
1 | import * as application from "tns-core-modules/application";
2 | application.run({ moduleName: "app-root" });
3 |
--------------------------------------------------------------------------------
/demo/app/main-page.ts:
--------------------------------------------------------------------------------
1 | import * as observable from "tns-core-modules/data/observable";
2 | import * as pages from "tns-core-modules/ui/page";
3 | import { HelloWorldModel } from "./main-view-model";
4 |
5 | // Event handler for Page 'loaded' event attached in main-page.xml
6 | export function pageLoaded(args: observable.EventData) {
7 | // Get the event sender
8 | const page = args.object;
9 | page.bindingContext = new HelloWorldModel();
10 | }
11 |
--------------------------------------------------------------------------------
/demo/app/main-page.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/demo/app/main-view-model.ts:
--------------------------------------------------------------------------------
1 | import { BiometricIDAvailableResult, FingerprintAuth } from "nativescript-fingerprint-auth";
2 | import { Observable } from "tns-core-modules/data/observable";
3 | import { alert } from "tns-core-modules/ui/dialogs";
4 |
5 | export class HelloWorldModel extends Observable {
6 | private fingerprintAuth: FingerprintAuth;
7 | public status: string = "Tap a button below..";
8 | private static CONFIGURED_PASSWORD = "MyPassword";
9 |
10 | constructor() {
11 | super();
12 | this.fingerprintAuth = new FingerprintAuth();
13 | }
14 |
15 | public doCheckAvailable(): void {
16 | this.fingerprintAuth
17 | .available()
18 | .then((result: BiometricIDAvailableResult) => {
19 | console.log("doCheckAvailable result: " + JSON.stringify(result));
20 | this.set(
21 | "status",
22 | "Biometric ID available? - " +
23 | (result.any ? (result.face ? "Face" : "Touch") : "NO")
24 | );
25 | })
26 | .catch(err => {
27 | console.log("doCheckAvailable error: " + err);
28 | this.set("status", "Error: " + err);
29 | });
30 | }
31 |
32 | public doCheckFingerprintsChanged(): void {
33 | this.fingerprintAuth
34 | .didFingerprintDatabaseChange()
35 | .then((changed: boolean) => {
36 | this.set(
37 | "status",
38 | "Biometric ID changed? - " + (changed ? "YES" : "NO")
39 | );
40 | });
41 | }
42 |
43 | public doVerifyFingerprint(): void {
44 | this.fingerprintAuth
45 | .verifyFingerprint({
46 | title: "Enter your password",
47 | message: "Scan yer finger", // optional
48 | authenticationValidityDuration: 10 // Android
49 | })
50 | .then(() => this.set("status", "Biometric ID / passcode OK"))
51 | .catch(err => {
52 | alert({
53 | title: "Biometric ID NOT OK / canceled",
54 | message: JSON.stringify(err),
55 | okButtonText: "Mmkay"
56 | });
57 | });
58 | }
59 |
60 | public doVerifyFingerprintWithCustomUI(): void {
61 | this.fingerprintAuth
62 | .verifyFingerprint({
63 | message: "Scan yer finger", // optional
64 | useCustomAndroidUI: true // Android
65 | })
66 | .then((enteredPassword?: string) => {
67 | if (enteredPassword === undefined) {
68 | this.set("status", "Biometric ID OK");
69 | } else {
70 | // compare enteredPassword to the one the user previously configured for your app (which is not the users system password!)
71 | if (enteredPassword === HelloWorldModel.CONFIGURED_PASSWORD) {
72 | this.set("status", "Biometric ID OK, using password");
73 | } else {
74 | this.set(
75 | "status",
76 | `Wrong password. Try '${HelloWorldModel.CONFIGURED_PASSWORD}' 😉`
77 | );
78 | }
79 | }
80 | })
81 | .catch(err =>
82 | this.set("status", `Biometric ID NOT OK: " + ${JSON.stringify(err)}`)
83 | );
84 | }
85 |
86 | public doVerifyFingerprintWithCustomFallback(): void {
87 | this.fingerprintAuth
88 | .verifyFingerprintWithCustomFallback({
89 | message: "Scan yer finger", // optional
90 | fallbackMessage: "Enter PIN", // optional
91 | authenticationValidityDuration: 10 // Android
92 | })
93 | .then(() => this.set("status", "Biometric ID OK"))
94 | .catch(error => {
95 | this.set("status", "Biometric ID NOT OK: " + JSON.stringify(error));
96 | alert({
97 | title: "Biometric ID NOT OK",
98 | message: error.code === -3 ? "Show custom fallback" : error.message,
99 | okButtonText: "Mmkay"
100 | });
101 | });
102 | }
103 | }
104 |
--------------------------------------------------------------------------------
/demo/app/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "android": {
3 | "v8Flags": "--expose_gc"
4 | },
5 | "main": "app.js",
6 | "name": "tns-template-hello-world",
7 | "version": "3.2.0"
8 | }
9 |
--------------------------------------------------------------------------------
/demo/app/res/telerik-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EddyVerbruggen/nativescript-fingerprint-auth/27461046c4479c0cd4d775fb72f5783e67742c39/demo/app/res/telerik-logo.png
--------------------------------------------------------------------------------
/demo/app/tests/tests.js:
--------------------------------------------------------------------------------
1 | var FingerprintAuth = require("nativescript-fingerprint-auth").FingerprintAuth;
2 | var fingerprintAuth = new FingerprintAuth();
3 |
4 | describe("available", function () {
5 | it("exists", function () {
6 | expect(fingerprintAuth.available).toBeDefined();
7 | });
8 |
9 | it("returns a promise", function () {
10 | expect(fingerprintAuth.available()).toEqual(jasmine.any(Promise));
11 | });
12 | });
13 |
14 | describe("verifyFingerprint", function () {
15 | it("exists", function () {
16 | expect(fingerprintAuth.verifyFingerprint).toBeDefined();
17 | });
18 |
19 | it("returns a promise", function () {
20 | expect(fingerprintAuth.verifyFingerprint()).toEqual(jasmine.any(Promise));
21 | });
22 | });
23 |
24 | describe("verifyFingerprintWithCustomFallback", function () {
25 | it("exists", function () {
26 | expect(fingerprintAuth.verifyFingerprintWithCustomFallback).toBeDefined();
27 | });
28 |
29 | it("returns a promise", function () {
30 | expect(fingerprintAuth.verifyFingerprintWithCustomFallback()).toEqual(jasmine.any(Promise));
31 | });
32 | });
33 |
34 | describe("didFingerprintDatabaseChange", function () {
35 | it("exists", function () {
36 | expect(fingerprintAuth.didFingerprintDatabaseChange).toBeDefined();
37 | });
38 |
39 | it("returns a promise", function () {
40 | expect(fingerprintAuth.didFingerprintDatabaseChange()).toEqual(jasmine.any(Promise));
41 | });
42 | });
43 |
--------------------------------------------------------------------------------
/demo/app/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "es5",
4 | "module": "commonjs",
5 | "declaration": false,
6 | "removeComments": true,
7 | "noLib": false,
8 | "emitDecoratorMetadata": true,
9 | "experimentalDecorators": true,
10 | "lib": [
11 | "dom",
12 | "es6"
13 | ],
14 | "pretty": true,
15 | "allowUnreachableCode": false,
16 | "allowUnusedLabels": false,
17 | "noEmitHelpers": true,
18 | "noEmitOnError": false,
19 | "noImplicitAny": false,
20 | "noImplicitReturns": true,
21 | "noImplicitUseStrict": false,
22 | "noFallthroughCasesInSwitch": true,
23 | "baseUrl": ".",
24 | "paths": {
25 | "*": [
26 | "./node_modules/*"
27 | ]
28 | }
29 | },
30 | "exclude": [
31 | "node_modules",
32 | "platforms"
33 | ],
34 | "compileOnSave": false
35 | }
--------------------------------------------------------------------------------
/demo/karma.conf.js:
--------------------------------------------------------------------------------
1 | module.exports = function (config) {
2 | const options = {
3 |
4 | // base path that will be used to resolve all patterns (eg. files, exclude)
5 | basePath: '',
6 |
7 |
8 | // frameworks to use
9 | // available frameworks: https://npmjs.org/browse/keyword/karma-adapter
10 | frameworks: ['jasmine'],
11 |
12 |
13 | // list of files / patterns to load in the browser
14 | files: ['app/tests/**/*.*'],
15 |
16 |
17 | // list of files to exclude
18 | exclude: [
19 | ],
20 |
21 |
22 | // preprocess matching files before serving them to the browser
23 | // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
24 | preprocessors: {
25 | },
26 |
27 |
28 | // test results reporter to use
29 | // possible values: 'dots', 'progress'
30 | // available reporters: https://npmjs.org/browse/keyword/karma-reporter
31 | reporters: ['progress'],
32 |
33 |
34 | // web server port
35 | port: 9876,
36 |
37 |
38 | // enable / disable colors in the output (reporters and logs)
39 | colors: true,
40 |
41 |
42 | // level of logging
43 | // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
44 | logLevel: config.LOG_INFO,
45 |
46 |
47 | // enable / disable watching file and executing tests whenever any file changes
48 | autoWatch: true,
49 |
50 |
51 | // start these browsers
52 | // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
53 | browsers: [],
54 |
55 | customLaunchers: {
56 | android: {
57 | base: 'NS',
58 | platform: 'android'
59 | },
60 | ios: {
61 | base: 'NS',
62 | platform: 'ios'
63 | },
64 | ios_simulator: {
65 | base: 'NS',
66 | platform: 'ios',
67 | arguments: ['--emulator']
68 | }
69 | },
70 |
71 | // Continuous Integration mode
72 | // if true, Karma captures browsers, runs the tests and exits
73 | singleRun: false
74 | };
75 |
76 | setWebpackPreprocessor(config, options);
77 | setWebpack(config, options);
78 |
79 | config.set(options);
80 | }
81 |
82 | function setWebpackPreprocessor(config, options) {
83 | if (config && config.bundle) {
84 | if (!options.preprocessors) {
85 | options.preprocessors = {};
86 | }
87 |
88 | options.files.forEach(file => {
89 | if (!options.preprocessors[file]) {
90 | options.preprocessors[file] = [];
91 | }
92 | options.preprocessors[file].push('webpack');
93 | });
94 | }
95 | }
96 |
97 | function setWebpack(config, options) {
98 | if (config && config.bundle) {
99 | const env = {};
100 | env[config.platform] = true;
101 | env.sourceMap = config.debugBrk;
102 | options.webpack = require('./webpack.config')(env);
103 | delete options.webpack.entry;
104 | delete options.webpack.output.libraryTarget;
105 | const invalidPluginsForUnitTesting = ["GenerateBundleStarterPlugin", "GenerateNativeScriptEntryPointsPlugin"];
106 | options.webpack.plugins = options.webpack.plugins.filter(p => !invalidPluginsForUnitTesting.includes(p.constructor.name));
107 | }
108 | }
109 |
--------------------------------------------------------------------------------
/demo/nsconfig.json:
--------------------------------------------------------------------------------
1 | {}
--------------------------------------------------------------------------------
/demo/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "nativescript": {
3 | "id": "org.nativescript.fingerprintauth",
4 | "tns-ios": {
5 | "version": "6.1.1"
6 | },
7 | "tns-android": {
8 | "version": "6.1.2"
9 | }
10 | },
11 | "dependencies": {
12 | "nativescript-fingerprint-auth": "file:../src",
13 | "nativescript-theme-core": "~1.0.6",
14 | "nativescript-unit-test-runner": "0.7.0",
15 | "tns-core-modules": "~6.1.1"
16 | },
17 | "devDependencies": {
18 | "tns-platform-declarations": "~6.1.1",
19 | "typescript": "3.4.5",
20 | "nativescript-dev-webpack": "~1.2.0",
21 | "karma-webpack": "3.0.5"
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/demo/references.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 | ///
3 |
--------------------------------------------------------------------------------
/demo/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "module": "commonjs",
4 | "target": "es5",
5 | "skipLibCheck": true,
6 | "noImplicitAny": false,
7 | "removeComments": true,
8 | "preserveConstEnums": true,
9 | "declaration": false,
10 | "noLib": false,
11 | "noEmitHelpers": true,
12 | "experimentalDecorators": true,
13 | "lib": [
14 | "es6",
15 | "dom"
16 | ],
17 | "baseUrl": ".",
18 | "paths": {
19 | "*": [
20 | "./node_modules/tns-core-modules/*",
21 | "./node_modules/*"
22 | ],
23 | "~/*": [
24 | "app/*"
25 | ]
26 | }
27 | },
28 | "exclude": [
29 | "node_modules",
30 | "platforms"
31 | ]
32 | }
--------------------------------------------------------------------------------
/demo/tsconfig.tns.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig",
3 | "compilerOptions": {
4 | "module": "esNext",
5 | "moduleResolution": "node"
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/demo/webpack.config.js:
--------------------------------------------------------------------------------
1 | const { join, relative, resolve, sep } = require("path");
2 |
3 | const webpack = require("webpack");
4 | const nsWebpack = require("nativescript-dev-webpack");
5 | const nativescriptTarget = require("nativescript-dev-webpack/nativescript-target");
6 | const CleanWebpackPlugin = require("clean-webpack-plugin");
7 | const CopyWebpackPlugin = require("copy-webpack-plugin");
8 | const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin');
9 | const { BundleAnalyzerPlugin } = require("webpack-bundle-analyzer");
10 | const { NativeScriptWorkerPlugin } = require("nativescript-worker-loader/NativeScriptWorkerPlugin");
11 | const TerserPlugin = require("terser-webpack-plugin");
12 | const hashSalt = Date.now().toString();
13 |
14 | module.exports = env => {
15 | // Add your custom Activities, Services and other Android app components here.
16 | const appComponents = [
17 | "tns-core-modules/ui/frame",
18 | "tns-core-modules/ui/frame/activity",
19 | ];
20 |
21 | const platform = env && (env.android && "android" || env.ios && "ios");
22 | if (!platform) {
23 | throw new Error("You need to provide a target platform!");
24 | }
25 |
26 | const platforms = ["ios", "android"];
27 | const projectRoot = __dirname;
28 |
29 | // Default destination inside platforms//...
30 | const dist = resolve(projectRoot, nsWebpack.getAppPath(platform, projectRoot));
31 |
32 | const {
33 | // The 'appPath' and 'appResourcesPath' values are fetched from
34 | // the nsconfig.json configuration file.
35 | appPath = "app",
36 | appResourcesPath = "app/App_Resources",
37 |
38 | // You can provide the following flags when running 'tns run android|ios'
39 | snapshot, // --env.snapshot
40 | production, // --env.production
41 | uglify, // --env.uglify
42 | report, // --env.report
43 | sourceMap, // --env.sourceMap
44 | hiddenSourceMap, // --env.hiddenSourceMap
45 | hmr, // --env.hmr,
46 | unitTesting, // --env.unitTesting,
47 | verbose, // --env.verbose
48 | } = env;
49 | const isAnySourceMapEnabled = !!sourceMap || !!hiddenSourceMap;
50 | const externals = nsWebpack.getConvertedExternals(env.externals);
51 |
52 | const appFullPath = resolve(projectRoot, appPath);
53 | const appResourcesFullPath = resolve(projectRoot, appResourcesPath);
54 |
55 | const entryModule = nsWebpack.getEntryModule(appFullPath, platform);
56 | const entryPath = `.${sep}${entryModule}.ts`;
57 | const entries = { bundle: entryPath };
58 |
59 | const tsConfigPath = resolve(projectRoot, "tsconfig.tns.json");
60 |
61 | const areCoreModulesExternal = Array.isArray(env.externals) && env.externals.some(e => e.indexOf("tns-core-modules") > -1);
62 | if (platform === "ios" && !areCoreModulesExternal) {
63 | entries["tns_modules/tns-core-modules/inspector_modules"] = "inspector_modules";
64 | };
65 |
66 | let sourceMapFilename = nsWebpack.getSourceMapFilename(hiddenSourceMap, __dirname, dist);
67 |
68 | const itemsToClean = [`${dist}/**/*`];
69 | if (platform === "android") {
70 | itemsToClean.push(`${join(projectRoot, "platforms", "android", "app", "src", "main", "assets", "snapshots")}`);
71 | itemsToClean.push(`${join(projectRoot, "platforms", "android", "app", "build", "configurations", "nativescript-android-snapshot")}`);
72 | }
73 |
74 | nsWebpack.processAppComponents(appComponents, platform);
75 | const config = {
76 | mode: production ? "production" : "development",
77 | context: appFullPath,
78 | externals,
79 | watchOptions: {
80 | ignored: [
81 | appResourcesFullPath,
82 | // Don't watch hidden files
83 | "**/.*",
84 | ]
85 | },
86 | target: nativescriptTarget,
87 | entry: entries,
88 | output: {
89 | pathinfo: false,
90 | path: dist,
91 | sourceMapFilename,
92 | libraryTarget: "commonjs2",
93 | filename: "[name].js",
94 | globalObject: "global",
95 | hashSalt
96 | },
97 | resolve: {
98 | extensions: [".ts", ".js", ".scss", ".css"],
99 | // Resolve {N} system modules from tns-core-modules
100 | modules: [
101 | resolve(__dirname, "node_modules/tns-core-modules"),
102 | resolve(__dirname, "node_modules"),
103 | "node_modules/tns-core-modules",
104 | "node_modules",
105 | ],
106 | alias: {
107 | '~': appFullPath
108 | },
109 | // resolve symlinks to symlinked modules
110 | symlinks: true
111 | },
112 | resolveLoader: {
113 | // don't resolve symlinks to symlinked loaders
114 | symlinks: false
115 | },
116 | node: {
117 | // Disable node shims that conflict with NativeScript
118 | "http": false,
119 | "timers": false,
120 | "setImmediate": false,
121 | "fs": "empty",
122 | "__dirname": false,
123 | },
124 | devtool: hiddenSourceMap ? "hidden-source-map" : (sourceMap ? "inline-source-map" : "none"),
125 | optimization: {
126 | runtimeChunk: "single",
127 | splitChunks: {
128 | cacheGroups: {
129 | vendor: {
130 | name: "vendor",
131 | chunks: "all",
132 | test: (module, chunks) => {
133 | const moduleName = module.nameForCondition ? module.nameForCondition() : '';
134 | return /[\\/]node_modules[\\/]/.test(moduleName) ||
135 | appComponents.some(comp => comp === moduleName);
136 |
137 | },
138 | enforce: true,
139 | },
140 | }
141 | },
142 | minimize: !!uglify,
143 | minimizer: [
144 | new TerserPlugin({
145 | parallel: true,
146 | cache: true,
147 | sourceMap: isAnySourceMapEnabled,
148 | terserOptions: {
149 | output: {
150 | comments: false,
151 | semicolons: !isAnySourceMapEnabled
152 | },
153 | compress: {
154 | // The Android SBG has problems parsing the output
155 | // when these options are enabled
156 | 'collapse_vars': platform !== "android",
157 | sequences: platform !== "android",
158 | }
159 | }
160 | })
161 | ],
162 | },
163 | module: {
164 | rules: [
165 | {
166 | include: join(appFullPath, entryPath),
167 | use: [
168 | // Require all Android app components
169 | platform === "android" && {
170 | loader: "nativescript-dev-webpack/android-app-components-loader",
171 | options: { modules: appComponents }
172 | },
173 |
174 | {
175 | loader: "nativescript-dev-webpack/bundle-config-loader",
176 | options: {
177 | loadCss: !snapshot, // load the application css if in debug mode
178 | unitTesting,
179 | appFullPath,
180 | projectRoot,
181 | ignoredFiles: nsWebpack.getUserDefinedEntries(entries, platform)
182 | }
183 | },
184 | ].filter(loader => !!loader)
185 | },
186 |
187 | {
188 | test: /\.(ts|css|scss|html|xml)$/,
189 | use: "nativescript-dev-webpack/hmr/hot-loader"
190 | },
191 |
192 | { test: /\.(html|xml)$/, use: "nativescript-dev-webpack/xml-namespace-loader" },
193 |
194 | {
195 | test: /\.css$/,
196 | use: { loader: "css-loader", options: { url: false } }
197 | },
198 |
199 | {
200 | test: /\.scss$/,
201 | use: [
202 | { loader: "css-loader", options: { url: false } },
203 | "sass-loader"
204 | ]
205 | },
206 |
207 | {
208 | test: /\.ts$/,
209 | use: {
210 | loader: "ts-loader",
211 | options: {
212 | configFile: tsConfigPath,
213 | // https://github.com/TypeStrong/ts-loader/blob/ea2fcf925ec158d0a536d1e766adfec6567f5fb4/README.md#faster-builds
214 | // https://github.com/TypeStrong/ts-loader/blob/ea2fcf925ec158d0a536d1e766adfec6567f5fb4/README.md#hot-module-replacement
215 | transpileOnly: true,
216 | allowTsInNodeModules: true,
217 | compilerOptions: {
218 | sourceMap: isAnySourceMapEnabled,
219 | declaration: false
220 | }
221 | },
222 | }
223 | },
224 | ]
225 | },
226 | plugins: [
227 | // Define useful constants like TNS_WEBPACK
228 | new webpack.DefinePlugin({
229 | "global.TNS_WEBPACK": "true",
230 | "process": "global.process",
231 | }),
232 | // Remove all files from the out dir.
233 | new CleanWebpackPlugin(itemsToClean, { verbose: !!verbose }),
234 | // Copy assets to out dir. Add your own globs as needed.
235 | new CopyWebpackPlugin([
236 | { from: { glob: "fonts/**" } },
237 | { from: { glob: "**/*.jpg" } },
238 | { from: { glob: "**/*.png" } },
239 | ], { ignore: [`${relative(appPath, appResourcesFullPath)}/**`] }),
240 | new nsWebpack.GenerateNativeScriptEntryPointsPlugin("bundle"),
241 | // For instructions on how to set up workers with webpack
242 | // check out https://github.com/nativescript/worker-loader
243 | new NativeScriptWorkerPlugin(),
244 | new nsWebpack.PlatformFSPlugin({
245 | platform,
246 | platforms,
247 | }),
248 | // Does IPC communication with the {N} CLI to notify events when running in watch mode.
249 | new nsWebpack.WatchStateLoggerPlugin(),
250 | // https://github.com/TypeStrong/ts-loader/blob/ea2fcf925ec158d0a536d1e766adfec6567f5fb4/README.md#faster-builds
251 | // https://github.com/TypeStrong/ts-loader/blob/ea2fcf925ec158d0a536d1e766adfec6567f5fb4/README.md#hot-module-replacement
252 | new ForkTsCheckerWebpackPlugin({
253 | tsconfig: tsConfigPath,
254 | async: false,
255 | useTypescriptIncrementalApi: true,
256 | memoryLimit: 4096
257 | })
258 | ],
259 | };
260 |
261 | if (report) {
262 | // Generate report files for bundles content
263 | config.plugins.push(new BundleAnalyzerPlugin({
264 | analyzerMode: "static",
265 | openAnalyzer: false,
266 | generateStatsFile: true,
267 | reportFilename: resolve(projectRoot, "report", `report.html`),
268 | statsFilename: resolve(projectRoot, "report", `stats.json`),
269 | }));
270 | }
271 |
272 | if (snapshot) {
273 | config.plugins.push(new nsWebpack.NativeScriptSnapshotPlugin({
274 | chunk: "vendor",
275 | requireModules: [
276 | "tns-core-modules/bundle-entry-points",
277 | ],
278 | projectRoot,
279 | webpackConfig: config,
280 | }));
281 | }
282 |
283 | if (hmr) {
284 | config.plugins.push(new webpack.HotModuleReplacementPlugin());
285 | }
286 |
287 |
288 | return config;
289 | };
290 |
--------------------------------------------------------------------------------
/media/fingerprint.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EddyVerbruggen/nativescript-fingerprint-auth/27461046c4479c0cd4d775fb72f5783e67742c39/media/fingerprint.png
--------------------------------------------------------------------------------
/media/ios-demo-01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EddyVerbruggen/nativescript-fingerprint-auth/27461046c4479c0cd4d775fb72f5783e67742c39/media/ios-demo-01.png
--------------------------------------------------------------------------------
/media/ios-demo-02.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EddyVerbruggen/nativescript-fingerprint-auth/27461046c4479c0cd4d775fb72f5783e67742c39/media/ios-demo-02.png
--------------------------------------------------------------------------------
/media/ios-demo-03.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EddyVerbruggen/nativescript-fingerprint-auth/27461046c4479c0cd4d775fb72f5783e67742c39/media/ios-demo-03.png
--------------------------------------------------------------------------------
/media/ios-demo-04.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EddyVerbruggen/nativescript-fingerprint-auth/27461046c4479c0cd4d775fb72f5783e67742c39/media/ios-demo-04.png
--------------------------------------------------------------------------------
/media/ios-demo-05.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EddyVerbruggen/nativescript-fingerprint-auth/27461046c4479c0cd4d775fb72f5783e67742c39/media/ios-demo-05.png
--------------------------------------------------------------------------------
/publish/pack.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | SOURCE_DIR=../src;
4 | TO_SOURCE_DIR=src;
5 | PACK_DIR=package;
6 | ROOT_DIR=..;
7 | PUBLISH=--publish
8 |
9 | install(){
10 | npm i
11 | }
12 |
13 | pack() {
14 |
15 | echo 'Clearing /src and /package...'
16 | node_modules/.bin/rimraf "$TO_SOURCE_DIR"
17 | node_modules/.bin/rimraf "$PACK_DIR"
18 |
19 | # copy src
20 | echo 'Copying src...'
21 | node_modules/.bin/ncp "$SOURCE_DIR" "$TO_SOURCE_DIR"
22 |
23 | # copy README & LICENSE to src
24 | echo 'Copying README and LICENSE to /src...'
25 | node_modules/.bin/ncp "$ROOT_DIR"/LICENSE "$TO_SOURCE_DIR"/LICENSE
26 | node_modules/.bin/ncp "$ROOT_DIR"/README.md "$TO_SOURCE_DIR"/README.md
27 |
28 | # compile package and copy files required by npm
29 | echo 'Building /src...'
30 | cd "$TO_SOURCE_DIR"
31 | node_modules/.bin/tsc
32 | cd ..
33 |
34 | echo 'Creating package...'
35 | # create package dir
36 | mkdir "$PACK_DIR"
37 |
38 | # create the package
39 | cd "$PACK_DIR"
40 | npm pack ../"$TO_SOURCE_DIR"
41 |
42 | # delete source directory used to create the package
43 | cd ..
44 | node_modules/.bin/rimraf "$TO_SOURCE_DIR"
45 | }
46 |
47 | install && pack
--------------------------------------------------------------------------------
/publish/package-lock.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "nativescript-publish",
3 | "version": "1.0.0",
4 | "lockfileVersion": 1,
5 | "requires": true,
6 | "dependencies": {
7 | "balanced-match": {
8 | "version": "1.0.0",
9 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
10 | "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
11 | "dev": true
12 | },
13 | "brace-expansion": {
14 | "version": "1.1.8",
15 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz",
16 | "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=",
17 | "dev": true,
18 | "requires": {
19 | "balanced-match": "^1.0.0",
20 | "concat-map": "0.0.1"
21 | }
22 | },
23 | "concat-map": {
24 | "version": "0.0.1",
25 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
26 | "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
27 | "dev": true
28 | },
29 | "fs.realpath": {
30 | "version": "1.0.0",
31 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
32 | "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
33 | "dev": true
34 | },
35 | "glob": {
36 | "version": "7.1.2",
37 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz",
38 | "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==",
39 | "dev": true,
40 | "requires": {
41 | "fs.realpath": "^1.0.0",
42 | "inflight": "^1.0.4",
43 | "inherits": "2",
44 | "minimatch": "^3.0.4",
45 | "once": "^1.3.0",
46 | "path-is-absolute": "^1.0.0"
47 | }
48 | },
49 | "inflight": {
50 | "version": "1.0.6",
51 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
52 | "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
53 | "dev": true,
54 | "requires": {
55 | "once": "^1.3.0",
56 | "wrappy": "1"
57 | }
58 | },
59 | "inherits": {
60 | "version": "2.0.3",
61 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
62 | "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=",
63 | "dev": true
64 | },
65 | "minimatch": {
66 | "version": "3.0.4",
67 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
68 | "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
69 | "dev": true,
70 | "requires": {
71 | "brace-expansion": "^1.1.7"
72 | }
73 | },
74 | "ncp": {
75 | "version": "2.0.0",
76 | "resolved": "https://registry.npmjs.org/ncp/-/ncp-2.0.0.tgz",
77 | "integrity": "sha1-GVoh1sRuNh0vsSgbo4uR6d9727M=",
78 | "dev": true
79 | },
80 | "once": {
81 | "version": "1.4.0",
82 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
83 | "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
84 | "dev": true,
85 | "requires": {
86 | "wrappy": "1"
87 | }
88 | },
89 | "path-is-absolute": {
90 | "version": "1.0.1",
91 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
92 | "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
93 | "dev": true
94 | },
95 | "rimraf": {
96 | "version": "2.6.2",
97 | "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz",
98 | "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==",
99 | "dev": true,
100 | "requires": {
101 | "glob": "^7.0.5"
102 | }
103 | },
104 | "wrappy": {
105 | "version": "1.0.2",
106 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
107 | "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
108 | "dev": true
109 | }
110 | }
111 | }
112 |
--------------------------------------------------------------------------------
/publish/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "nativescript-publish",
3 | "version": "1.0.0",
4 | "description": "Publish helper",
5 | "devDependencies": {
6 | "ncp": "^2.0.0",
7 | "rimraf": "^2.5.0"
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/publish/publish.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | PACK_DIR=package;
4 |
5 | publish() {
6 | cd $PACK_DIR
7 | echo 'Publishing to npm...'
8 | npm publish *.tgz
9 | }
10 |
11 | ./pack.sh && publish
--------------------------------------------------------------------------------
/src/.npmignore:
--------------------------------------------------------------------------------
1 | *.map
2 | *.ts
3 | !*.d.ts
4 | tsconfig.json
5 | package-lock.json
6 | references.d.ts
7 | platforms/android/*
8 | !platforms/android/include.gradle
9 | !platforms/android/*.aar
10 |
--------------------------------------------------------------------------------
/src/fingerprint-auth.android.ts:
--------------------------------------------------------------------------------
1 | import * as app from "tns-core-modules/application";
2 | import { AndroidActivityResultEventData } from "tns-core-modules/application";
3 | import { ad as androidUtils } from "tns-core-modules/utils/utils";
4 | import { BiometricIDAvailableResult, ERROR_CODES, FingerprintAuthApi, VerifyFingerprintOptions, VerifyFingerprintWithCustomFallbackOptions } from "./fingerprint-auth.common";
5 |
6 | declare const com: any;
7 |
8 | const KEY_NAME = "fingerprintauth";
9 | const SECRET_BYTE_ARRAY = Array.create("byte", 16);
10 | const REQUEST_CODE_CONFIRM_DEVICE_CREDENTIALS = 788; // arbitrary
11 |
12 | export class FingerprintAuth implements FingerprintAuthApi {
13 | private keyguardManager: android.app.KeyguardManager;
14 | private fingerPrintManager: any;
15 |
16 | constructor() {
17 | this.keyguardManager = androidUtils
18 | .getApplicationContext()
19 | .getSystemService("keyguard");
20 | }
21 |
22 | // TODO can we detect face on the Samsung S8?
23 | available(): Promise {
24 | return new Promise((resolve, reject) => {
25 | try {
26 | if (!this.keyguardManager || !this.keyguardManager.isKeyguardSecure()) {
27 | resolve({
28 | any: false
29 | });
30 | return;
31 | }
32 |
33 | // The fingerprint API is only available from Android 6.0 (M, Api level 23)
34 | if (android.os.Build.VERSION.SDK_INT < 23) {
35 | reject(`Your api version doesn't support fingerprint authentication`);
36 | return;
37 | }
38 |
39 | const fingerprintManager = androidUtils
40 | .getApplicationContext()
41 | .getSystemService(
42 | "fingerprint"
43 | ) as android.hardware.fingerprint.FingerprintManager;
44 |
45 | if (!fingerprintManager || !fingerprintManager.isHardwareDetected()) {
46 | // Device doesn't support fingerprint authentication
47 | reject(`Device doesn't support fingerprint authentication`);
48 | } else if (!fingerprintManager.hasEnrolledFingerprints()) {
49 | // If the user has not enrolled any fingerprints, they still might have the device secure so we can fallback
50 | // to present the user with the swipe, password, pin device security screen regardless
51 | // the developer can handle this resolve by checking the `touch` property and determine if they want to use the
52 | // verifyFingerprint method or not since they'll know the user has no finger prints enrolled but do have a security option enabled
53 | // https://developer.android.com/reference/android/app/KeyguardManager.html#isDeviceSecure() only 23+
54 | if (this.keyguardManager.isDeviceSecure()) {
55 | resolve({
56 | any: true,
57 | touch: false
58 | });
59 | } else {
60 | // User hasn't enrolled any fingerprints to authenticate with
61 | reject(
62 | `User hasn't enrolled any fingerprints to authenticate with`
63 | );
64 | }
65 | } else {
66 | resolve({
67 | any: true,
68 | touch: true
69 | });
70 | }
71 | } catch (ex) {
72 | console.log(`fingerprint-auth.available: ${ex}`);
73 | reject(ex);
74 | }
75 | });
76 | }
77 |
78 | didFingerprintDatabaseChange(): Promise {
79 | return new Promise((resolve, reject) => {
80 | // not implemented for Android
81 | // TODO should be possible..
82 | resolve(false);
83 | });
84 | }
85 |
86 | private verifyWithCustomAndroidUI(resolve, reject, authenticationCallback) {
87 | // this instance is com.jesusm.kfingerprintmanager.KFingerprintManager, not the android OS fingerprint manager
88 | this.fingerPrintManager.authenticate(
89 | authenticationCallback,
90 | this.getActivity().getSupportFragmentManager()
91 | );
92 | }
93 |
94 | verifyFingerprint(options: VerifyFingerprintOptions): Promise {
95 | return new Promise((resolve, reject) => {
96 | try {
97 | // in case 'activity.getSupportFragmentManager' is available ({N} started supporting it,
98 | // or the user added our Activity to their Android manifest), use the 3rd party FP library
99 | const hasSupportFragment =
100 | this.getActivity().getSupportFragmentManager !== undefined;
101 |
102 | if (options.useCustomAndroidUI && !hasSupportFragment) {
103 | reject({
104 | code: ERROR_CODES.DEVELOPER_ERROR,
105 | message:
106 | "Custom Fingerprint UI requires changes to AndroidManifest.xml. See the nativescript-fingerprint-auth documentation."
107 | });
108 | } else if (options.useCustomAndroidUI && hasSupportFragment) {
109 | if (!this.fingerPrintManager) {
110 | this.fingerPrintManager = new com.jesusm.kfingerprintmanager.KFingerprintManager(
111 | androidUtils.getApplicationContext(),
112 | KEY_NAME
113 | );
114 | }
115 | const that = this;
116 | const callback = new com.jesusm.kfingerprintmanager.KFingerprintManager.AuthenticationCallback(
117 | {
118 | attempts: 0,
119 | onAuthenticationFailedWithHelp(help): void {
120 | if (++this.attempts < 3) {
121 | // just invoke the UI again as it's very sensitive (need a timeout to prevent an infinite loop)
122 | setTimeout(
123 | () => that.verifyWithCustomAndroidUI(resolve, reject, this),
124 | 50
125 | );
126 | } else {
127 | reject({
128 | code: ERROR_CODES.RECOVERABLE_ERROR,
129 | message: help
130 | });
131 | }
132 | },
133 | onAuthenticationSuccess(): void {
134 | resolve();
135 | },
136 | onSuccessWithManualPassword(password): void {
137 | resolve(password);
138 | },
139 | onFingerprintNotRecognized(): void {
140 | if (++this.attempts < 3) {
141 | // just invoke the UI again as it's very sensitive (need a timeout to prevent an infinite loop)
142 | setTimeout(
143 | () => that.verifyWithCustomAndroidUI(resolve, reject, this),
144 | 50
145 | );
146 | } else {
147 | reject({
148 | code: ERROR_CODES.NOT_RECOGNIZED,
149 | message: "Fingerprint not recognized."
150 | });
151 | }
152 | },
153 | onFingerprintNotAvailable(): void {
154 | reject({
155 | code: ERROR_CODES.NOT_CONFIGURED,
156 | message:
157 | 'Secure lock screen hasn\'t been set up.\n Go to "Settings -> Security -> Screenlock" to set up a lock screen.'
158 | });
159 | },
160 | onCancelled(): void {
161 | reject({
162 | code: ERROR_CODES.PASSWORD_FALLBACK_SELECTED,
163 | message: "Cancelled by user"
164 | });
165 | }
166 | }
167 | );
168 | this.verifyWithCustomAndroidUI(resolve, reject, callback);
169 | } else {
170 | const onActivityResult = (data: AndroidActivityResultEventData) => {
171 | if (data.requestCode === REQUEST_CODE_CONFIRM_DEVICE_CREDENTIALS) {
172 | if (data.resultCode === android.app.Activity.RESULT_OK) {
173 | // OK = -1
174 | // the user has just authenticated via the ConfirmDeviceCredential activity
175 | resolve();
176 | } else {
177 | // the user has quit the activity without providing credentials
178 | reject({
179 | code: ERROR_CODES.USER_CANCELLED,
180 | message: "User cancelled."
181 | });
182 | }
183 | }
184 | app.android.off(
185 | app.AndroidApplication.activityResultEvent,
186 | onActivityResult
187 | );
188 | };
189 |
190 | app.android.on(
191 | app.AndroidApplication.activityResultEvent,
192 | onActivityResult
193 | );
194 |
195 | if (!this.keyguardManager) {
196 | reject({
197 | code: ERROR_CODES.NOT_AVAILABLE,
198 | message: "Keyguard manager not available."
199 | });
200 | }
201 | if (
202 | this.keyguardManager &&
203 | !this.keyguardManager.isKeyguardSecure()
204 | ) {
205 | reject({
206 | code: ERROR_CODES.NOT_CONFIGURED,
207 | message:
208 | 'Secure lock screen hasn\'t been set up.\n Go to "Settings -> Security -> Screenlock" to set up a lock screen.'
209 | });
210 | }
211 |
212 | FingerprintAuth.createKey(options);
213 |
214 | const tryEncryptResult: boolean = this.tryEncrypt(options);
215 | if (tryEncryptResult === undefined) {
216 | // this one is async
217 | } else if (tryEncryptResult === true) {
218 | resolve();
219 | } else {
220 | reject({
221 | code: ERROR_CODES.UNEXPECTED_ERROR,
222 | message: "See the console for error logs."
223 | });
224 | }
225 | }
226 | } catch (ex) {
227 | console.log(`Error in fingerprint-auth.verifyFingerprint: ${ex}`);
228 | reject({
229 | code: ERROR_CODES.UNEXPECTED_ERROR,
230 | message: ex
231 | });
232 | }
233 | });
234 | }
235 |
236 | verifyFingerprintWithCustomFallback(
237 | options: VerifyFingerprintWithCustomFallbackOptions
238 | ): Promise {
239 | return this.verifyFingerprint(options);
240 | }
241 |
242 | close(): void {
243 | const fragmentManager = this.getActivity().getSupportFragmentManager();
244 | // this is for custom ui
245 | const fragmentTag = "KFingerprintManager:fingerprintDialog";
246 | const fragment = fragmentManager.findFragmentByTag(fragmentTag);
247 | if (fragment) {
248 | fragmentManager.beginTransaction().remove(fragment).commit();
249 | } else {
250 | // AFAIK it's not possible to programmatically close the standard one
251 | }
252 | }
253 |
254 | /**
255 | * Creates a symmetric key in the Android Key Store which can only be used after the user has
256 | * authenticated with device credentials within the last X seconds.
257 | */
258 | private static createKey(options): void {
259 | try {
260 | const keyStore = java.security.KeyStore.getInstance("AndroidKeyStore");
261 | keyStore.load(null);
262 | const keyGenerator = javax.crypto.KeyGenerator.getInstance(
263 | android.security.keystore.KeyProperties.KEY_ALGORITHM_AES,
264 | "AndroidKeyStore"
265 | );
266 |
267 | keyGenerator.init(
268 | new android.security.keystore.KeyGenParameterSpec.Builder(
269 | KEY_NAME,
270 | android.security.keystore.KeyProperties.PURPOSE_ENCRYPT |
271 | android.security.keystore.KeyProperties.PURPOSE_DECRYPT
272 | )
273 | .setBlockModes([
274 | android.security.keystore.KeyProperties.BLOCK_MODE_CBC
275 | ])
276 | .setUserAuthenticationRequired(true)
277 | .setUserAuthenticationValidityDurationSeconds(
278 | options && options.authenticationValidityDuration
279 | ? options.authenticationValidityDuration
280 | : 5
281 | )
282 | .setEncryptionPaddings([
283 | android.security.keystore.KeyProperties.ENCRYPTION_PADDING_PKCS7
284 | ])
285 | .build()
286 | );
287 | keyGenerator.generateKey();
288 | } catch (error) {
289 | // checks if the AES algorithm is implemented by the AndroidKeyStore
290 | if (
291 | `${error.nativeException}`.indexOf(
292 | "java.security.NoSuchAlgorithmException:"
293 | ) > -1
294 | ) {
295 | // You need a device with API level >= 23 in order to detect if the user has already been authenticated in the last x seconds.
296 | }
297 | }
298 | }
299 |
300 | private tryEncrypt(options): boolean {
301 | try {
302 | const keyStore = java.security.KeyStore.getInstance("AndroidKeyStore");
303 | keyStore.load(null);
304 | const secretKey = keyStore.getKey(KEY_NAME, null);
305 |
306 | const cipher = javax.crypto.Cipher.getInstance(
307 | `${android.security.keystore.KeyProperties.KEY_ALGORITHM_AES}/${
308 | android.security.keystore.KeyProperties.BLOCK_MODE_CBC
309 | }/${android.security.keystore.KeyProperties.ENCRYPTION_PADDING_PKCS7}`
310 | );
311 |
312 | cipher.init(javax.crypto.Cipher.ENCRYPT_MODE, secretKey);
313 | cipher.doFinal(SECRET_BYTE_ARRAY);
314 |
315 | return true;
316 | } catch (error) {
317 | if (
318 | `${error.nativeException}`.indexOf(
319 | "android.security.keystore.UserNotAuthenticatedException"
320 | ) > -1
321 | ) {
322 | // the user must provide their credentials in order to proceed
323 | this.showAuthenticationScreen(options);
324 | return undefined;
325 | } else if (
326 | `${error.nativeException}`.indexOf(
327 | "android.security.keystore.KeyPermanentlyInvalidatedException"
328 | ) > -1
329 | ) {
330 | // Invalid fingerprint
331 | console.log(error);
332 | } else {
333 | console.log(error);
334 | }
335 | return false;
336 | }
337 | }
338 |
339 | /**
340 | * Starts the built-in Android ConfirmDeviceCredential activity.
341 | */
342 | private showAuthenticationScreen(options): void {
343 | // https://developer.android.com/reference/android/app/KeyguardManager#createConfirmDeviceCredentialIntent(java.lang.CharSequence,%2520java.lang.CharSequence)
344 | const intent = (this
345 | .keyguardManager as any).createConfirmDeviceCredentialIntent(
346 | options && options.title ? options.title : null,
347 | options && options.message ? options.message : null
348 | );
349 | if (intent !== null) {
350 | this.getActivity().startActivityForResult(
351 | intent,
352 | REQUEST_CODE_CONFIRM_DEVICE_CREDENTIALS
353 | );
354 | }
355 | }
356 |
357 | private getActivity(): any /* android.app.Activity */ {
358 | return app.android.foregroundActivity || app.android.startActivity;
359 | }
360 | }
361 |
--------------------------------------------------------------------------------
/src/fingerprint-auth.common.ts:
--------------------------------------------------------------------------------
1 | export enum ERROR_CODES {
2 | PASSWORD_FALLBACK_SELECTED = -3, // historically this is what iOS uses, so using that as well
3 | DEVELOPER_ERROR = 10,
4 | NOT_AVAILABLE = 20,
5 | NOT_CONFIGURED = 30,
6 | NOT_RECOGNIZED = 40,
7 | RECOVERABLE_ERROR = 50,
8 | USER_CANCELLED = 60,
9 | UNEXPECTED_ERROR = 70
10 | }
11 |
12 | export interface VerifyFingerprintOptions {
13 | /**
14 | * The optional title in the fingerprint page for android.
15 | * Default: whatever the device default is ('Confirm your password' is likely)
16 | */
17 | title?: string;
18 |
19 | /**
20 | * The optional message in the fingerprint dialog on ios and page description on android.
21 | * Default: 'Scan your finger' on iOS and the device default on Android (which is likely 'Enter your device password to continue').
22 | */
23 | message?: string;
24 |
25 | /**
26 | * Default 5 (seconds). Can be 0 to always trigger auth.
27 | * Android only.
28 | */
29 | authenticationValidityDuration?: number;
30 |
31 | /**
32 | * On Android you can either use our fancy proprietary UI or the stock UI Android ships with.
33 | * Default false (so use the default UI).
34 | * Android only.
35 | */
36 | useCustomAndroidUI?: boolean;
37 | }
38 |
39 | export interface VerifyFingerprintWithCustomFallbackOptions {
40 | /**
41 | * The optional message in the fingerprint dialog.
42 | * Default: 'Scan your finger'.
43 | */
44 | message?: string;
45 |
46 | /**
47 | * The optional button label when scanning the fingerprint fails.
48 | * Default: 'Enter password'.
49 | */
50 | fallbackMessage?: string;
51 |
52 | /**
53 | * Default 5 (seconds). Can be 0 to always trigger auth.
54 | * Android only.
55 | */
56 | authenticationValidityDuration?: number;
57 | }
58 |
59 | export interface BiometricIDAvailableResult {
60 | any: boolean;
61 | touch?: boolean;
62 | face?: boolean;
63 | }
64 |
65 | //noinspection JSUnusedGlobalSymbols
66 | export interface FingerprintAuthApi {
67 | available(): Promise;
68 |
69 | didFingerprintDatabaseChange(): Promise;
70 | /**
71 | * This (recommended) method uses keychain instead of localauth so the passcode fallback can be used.
72 | * On Android, when 'useCustomAndroidUI' is set to 'true', and the user opted for manually entering the password,
73 | * this method may return a string (the entered password) for you to compare to the actual password.
74 | */
75 | verifyFingerprint(options: VerifyFingerprintOptions): Promise;
76 |
77 | /**
78 | * This implementation uses LocalAuthentication and has no built-in passcode fallback on iOS.
79 | * On Android this is exactly the same as 'verifyFingerprint'
80 | */
81 | verifyFingerprintWithCustomFallback(
82 | options: VerifyFingerprintWithCustomFallbackOptions
83 | ): Promise;
84 |
85 | close(): void;
86 | }
87 |
--------------------------------------------------------------------------------
/src/fingerprint-auth.ios.ts:
--------------------------------------------------------------------------------
1 | import { ios as iOSUtils } from "tns-core-modules/utils/utils";
2 | import {
3 | BiometricIDAvailableResult,
4 | FingerprintAuthApi,
5 | VerifyFingerprintOptions,
6 | VerifyFingerprintWithCustomFallbackOptions
7 | } from "./fingerprint-auth.common";
8 |
9 | const keychainItemIdentifier = "TouchIDKey";
10 | let keychainItemServiceName = null;
11 |
12 | export class FingerprintAuth implements FingerprintAuthApi {
13 | private laContext: LAContext;
14 |
15 | available(): Promise {
16 | return new Promise((resolve, reject) => {
17 | try {
18 | const laContext = LAContext.new();
19 | const hasBio = laContext.canEvaluatePolicyError(LAPolicy.DeviceOwnerAuthenticationWithBiometrics);
20 |
21 | resolve({
22 | any: hasBio,
23 | touch: hasBio && laContext.biometryType === 1, // LABiometryType.TypeTouchID,
24 | face: hasBio && laContext.biometryType === 2 // LABiometryType.TypeFaceID,
25 | });
26 | } catch (ex) {
27 | console.log(`fingerprint-auth.available: ${ex}`);
28 | // if no identities are enrolled, there will be an exception (so not using 'reject' here)
29 | resolve({
30 | any: false
31 | });
32 | }
33 | });
34 | }
35 |
36 | didFingerprintDatabaseChange(): Promise {
37 | return new Promise((resolve, reject) => {
38 | try {
39 | const laContext = LAContext.new();
40 |
41 | // we expect the dev to have checked 'isAvailable' already so this should not return an error,
42 | // we do however need to run canEvaluatePolicy here in order to get a non-nil evaluatedPolicyDomainState
43 | if (!laContext.canEvaluatePolicyError(LAPolicy.DeviceOwnerAuthenticationWithBiometrics)) {
44 | reject("Not available");
45 | return;
46 | }
47 |
48 | // only supported on iOS9+, so check this.. if not supported just report back as false
49 | if (iOSUtils.MajorVersion < 9) {
50 | resolve(false);
51 | return;
52 | }
53 |
54 | const FingerprintDatabaseStateKey = "FingerprintDatabaseStateKey";
55 | const state = laContext.evaluatedPolicyDomainState;
56 | if (state !== null) {
57 | const stateStr = state.base64EncodedStringWithOptions(0);
58 | const storedState = NSUserDefaults.standardUserDefaults.stringForKey(FingerprintDatabaseStateKey);
59 |
60 | // Store enrollment
61 | NSUserDefaults.standardUserDefaults.setObjectForKey(stateStr, FingerprintDatabaseStateKey);
62 | NSUserDefaults.standardUserDefaults.synchronize();
63 |
64 | // whenever a finger is added/changed/removed the value of the storedState changes,
65 | // so compare agains a value we previously stored in the context of this app
66 | const changed = storedState !== null && stateStr !== storedState;
67 | resolve(changed);
68 | }
69 | } catch (ex) {
70 | console.log(`Error in fingerprint-auth.didFingerprintDatabaseChange: ${ex}`);
71 | resolve(false);
72 | }
73 | });
74 | }
75 |
76 | /**
77 | * this 'default' method uses keychain instead of localauth so the passcode fallback can be used
78 | */
79 | verifyFingerprint(options: VerifyFingerprintOptions): Promise {
80 | return new Promise((resolve, reject) => {
81 | try {
82 | if (keychainItemServiceName === null) {
83 | const bundleID = NSBundle.mainBundle.infoDictionary.objectForKey("CFBundleIdentifier");
84 | keychainItemServiceName = `${bundleID}.TouchID`;
85 | }
86 |
87 | if (!FingerprintAuth.createKeyChainEntry()) {
88 | this.verifyFingerprintWithCustomFallback(options, true).then(
89 | resolve,
90 | reject
91 | );
92 | return;
93 | }
94 |
95 | const query = NSMutableDictionary.alloc().init();
96 | query.setObjectForKey(kSecClassGenericPassword, kSecClass);
97 | query.setObjectForKey(keychainItemIdentifier, kSecAttrAccount);
98 | query.setObjectForKey(keychainItemServiceName, kSecAttrService);
99 |
100 | // Note that you can only do this for Touch ID; for Face ID you need to tweak the plist value of NSFaceIDUsageDescription
101 | query.setObjectForKey(
102 | (options !== null && options.message) || "Scan your finger",
103 | kSecUseOperationPrompt
104 | );
105 |
106 | // Start the query and the fingerprint scan and/or device passcode validation
107 | const res = SecItemCopyMatching(query, null);
108 | if (res === 0) {
109 | resolve();
110 | } else {
111 | reject();
112 | }
113 | } catch (ex) {
114 | console.log(`Error in fingerprint-auth.verifyFingerprint: ${ex}`);
115 | reject(ex);
116 | }
117 | });
118 | }
119 |
120 | /**
121 | * This implementation uses LocalAuthentication and has no built-in passcode fallback
122 | */
123 | verifyFingerprintWithCustomFallback(
124 | options: VerifyFingerprintWithCustomFallbackOptions,
125 | usePasscodeFallback = false
126 | ): Promise {
127 | return new Promise((resolve, reject) => {
128 | try {
129 | this.laContext = LAContext.new();
130 | if (!this.laContext.canEvaluatePolicyError(LAPolicy.DeviceOwnerAuthenticationWithBiometrics)) {
131 | reject("Not available");
132 | return;
133 | }
134 |
135 | const message = (options !== null && options.message) || "Scan your finger";
136 | if (options !== null && options.fallbackMessage) {
137 | this.laContext.localizedFallbackTitle = options.fallbackMessage;
138 | }
139 | this.laContext.evaluatePolicyLocalizedReasonReply(
140 | usePasscodeFallback ? LAPolicy.DeviceOwnerAuthentication : LAPolicy.DeviceOwnerAuthenticationWithBiometrics,
141 | message,
142 | (ok, error) => {
143 | if (ok) {
144 | resolve();
145 | } else {
146 | reject({
147 | code: error.code,
148 | message: error.localizedDescription
149 | });
150 | }
151 | }
152 | );
153 | } catch (ex) {
154 | console.log(`Error in fingerprint-auth.verifyFingerprint: ${ex}`);
155 | reject(ex);
156 | }
157 | });
158 | }
159 |
160 | private static createKeyChainEntry(): boolean {
161 | const attributes = NSMutableDictionary.new();
162 | attributes.setObjectForKey(kSecClassGenericPassword, kSecClass);
163 | attributes.setObjectForKey(keychainItemIdentifier, kSecAttrAccount);
164 | attributes.setObjectForKey(keychainItemServiceName, kSecAttrService);
165 |
166 | const accessControlRef = SecAccessControlCreateWithFlags(
167 | kCFAllocatorDefault,
168 | kSecAttrAccessibleWhenUnlockedThisDeviceOnly,
169 | 2, // either SecAccessControlCreateFlags.kSecAccessControlBiometryAny (iOS 11.3+), or SecAccessControlCreateFlags.kSecAccessControlTouchIDAny (iOS < 11.3)
170 | null
171 | );
172 | if (accessControlRef === null) {
173 | console.log(`Can't store identifier '${keychainItemIdentifier}' in the KeyChain.`);
174 | return false;
175 | } else {
176 | attributes.setObjectForKey(accessControlRef, kSecAttrAccessControl);
177 | // The content of the password is not important
178 | const content = NSString.stringWithString("dummy content");
179 | const nsData = content.dataUsingEncoding(NSUTF8StringEncoding);
180 | attributes.setObjectForKey(nsData, kSecValueData);
181 |
182 | SecItemAdd(attributes, null);
183 | return true;
184 | }
185 | }
186 |
187 | close(): void {
188 | if (this.laContext) {
189 | this.laContext.invalidate();
190 | }
191 | }
192 | }
193 |
--------------------------------------------------------------------------------
/src/index.d.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * iOS and Android apis should match.
3 | * It doesn't matter if you export `.ios` or `.android`, either one but only one.
4 | */
5 | export * from "./fingerprint-auth.ios";
6 |
7 | // Export any shared classes, constants, etc.
8 | export * from "./fingerprint-auth.common";
--------------------------------------------------------------------------------
/src/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "nativescript-fingerprint-auth",
3 | "version": "7.0.2",
4 | "description": "A fingerprint authentication plugin for use in NativeScript apps",
5 | "main": "fingerprint-auth",
6 | "nativescript": {
7 | "platforms": {
8 | "android": "5.4.0",
9 | "ios": "3.0.0"
10 | }
11 | },
12 | "snapshot": {
13 | "android": {
14 | "tns-java-classes": {
15 | "modules": [
16 | "nativescript-fingerprint-auth/appcompat-activity"
17 | ]
18 | }
19 | }
20 | },
21 | "scripts": {
22 | "build": "npm i && tsc",
23 | "demo.ios": "npm run preparedemo && cd ../demo && tns run ios",
24 | "demo.android": "npm run preparedemo && cd ../demo && tns platform remove android && tns run android",
25 | "test": "npm run tslint && npm run tslint.demo && cd ../demo && tns build ios && tns build android",
26 | "test.ios": "cd ../demo && tns platform remove ios && tns test ios --emulator",
27 | "test.ios.device": "cd ../demo && tns platform remove ios && tns test ios",
28 | "test.android": "cd ../demo && tns platform remove android && tns test android --justlaunch",
29 | "preparedemo": "npm run build && cd ../demo && tns plugin remove nativescript-fingerprint-auth && tns plugin add ../src && tns install",
30 | "setup": "npm run build && cd ../demo && npm i",
31 | "setupandinstall": "npm i && cd ../demo && npm i && cd ../src && npm run build && cd ../demo && tns plugin add ../src && cd ../src",
32 | "tslint": "tslint --config '../tslint.json' '*.ts' --exclude '**/node_modules/**'",
33 | "tslint.demo": "tslint --config '../tslint.json' '../demo/app/*.ts' --exclude '**/node_modules/**'",
34 | "ci.tslint": "npm run tslint && npm run tslint.demo",
35 | "prepublishOnly": "npm run build",
36 | "development.setup": "npm run setup && npm link && cd ../demo && npm link nativescript-fingerprint-auth && cd ../src"
37 | },
38 | "repository": {
39 | "type": "git",
40 | "url": "https://github.com/eddyverbruggen/nativescript-fingerprint-auth.git"
41 | },
42 | "keywords": [
43 | "NativeScript",
44 | "ecosystem:nativescript",
45 | "iOS",
46 | "Android",
47 | "TouchID",
48 | "Touch ID",
49 | "FaceID",
50 | "Biometric",
51 | "Biometric ID",
52 | "Fingerprint",
53 | "Fingerprint scanner",
54 | "Face ID",
55 | "Face scanner"
56 | ],
57 | "author": {
58 | "name": "Eddy Verbruggen",
59 | "email": "eddyverbruggen@gmail.com"
60 | },
61 | "license": "MIT",
62 | "bugs": {
63 | "url": "https://github.com/eddyverbruggen/nativescript-fingerprint-auth/issues"
64 | },
65 | "homepage": "https://github.com/eddyverbruggen/nativescript-fingerprint-auth",
66 | "readmeFilename": "README.md",
67 | "devDependencies": {
68 | "tns-core-modules": "~6.1.1",
69 | "tns-platform-declarations": "~6.1.1",
70 | "typescript": "~3.4.5",
71 | "tslint": "^5.17.0"
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/src/platforms/android/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/src/platforms/android/include.gradle:
--------------------------------------------------------------------------------
1 | android {
2 | }
3 |
4 | repositories {
5 | maven { url 'https://jitpack.io' }
6 | }
7 |
8 | dependencies {
9 | implementation 'com.github.JesusM:FingerprintManager:v2.0.2'
10 | }
11 |
--------------------------------------------------------------------------------
/src/platforms/ios/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | NSFaceIDUsageDescription
6 |
7 |
8 |
--------------------------------------------------------------------------------
/src/references.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 | ///
3 |
--------------------------------------------------------------------------------
/src/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "es5",
4 | "module": "commonjs",
5 | "declaration": true,
6 | "removeComments": true,
7 | "noLib": false,
8 | "emitDecoratorMetadata": true,
9 | "experimentalDecorators": true,
10 | "skipLibCheck": true,
11 | "lib": [
12 | "es6",
13 | "dom"
14 | ],
15 | "sourceMap": false,
16 | "pretty": true,
17 | "allowUnreachableCode": false,
18 | "allowUnusedLabels": false,
19 | "noEmitHelpers": true,
20 | "noEmitOnError": false,
21 | "noImplicitAny": false,
22 | "noImplicitReturns": true,
23 | "noImplicitUseStrict": false,
24 | "noFallthroughCasesInSwitch": true,
25 | "typeRoots": [
26 | "./node_modules/@types",
27 | "./node_modules"
28 | ],
29 | "types": [
30 | ]
31 | },
32 | "exclude": [
33 | "demo",
34 | "node_modules"
35 | ],
36 | "compileOnSave": false
37 | }
38 |
--------------------------------------------------------------------------------
/tslint.json:
--------------------------------------------------------------------------------
1 | {
2 | "rules": {
3 | "class-name": true,
4 | "prefer-const": true,
5 | "comment-format": [true, "check-space"],
6 | "indent": [true, "spaces"],
7 | "no-duplicate-variable": true,
8 | "no-eval": true,
9 | "no-internal-module": true,
10 | "no-trailing-whitespace": true,
11 | "no-var-keyword": true,
12 | "one-line": [true, "check-open-brace", "check-whitespace"],
13 | "quotemark": [false, "double"],
14 | "semicolon": [true, "always"],
15 | "triple-equals": [true, "allow-null-check"],
16 | "typedef-whitespace": [
17 | true,
18 | {
19 | "call-signature": "nospace",
20 | "index-signature": "nospace",
21 | "parameter": "nospace",
22 | "property-declaration": "nospace",
23 | "variable-declaration": "nospace"
24 | }
25 | ],
26 | "variable-name": [true, "ban-keywords"],
27 | "whitespace": [
28 | true,
29 | "check-branch",
30 | "check-decl",
31 | "check-operator",
32 | "check-separator",
33 | "check-type"
34 | ]
35 | }
36 | }
37 |
--------------------------------------------------------------------------------