1
- exports . available = function ( ) {
1
+
2
+ var app = require ( 'application' ) ;
3
+ var utils = require ( 'utils/utils' ) ;
4
+
5
+ var KeyguardManager = android . app . KeyguardManager ;
6
+ var ActivityCompat = android . support . v4 . app . ActivityCompat ;
7
+ var Manifest = android . Manifest ;
8
+ var PackageManager = android . content . pm . PackageManager ;
9
+ var KeyStore = java . security . KeyStore ;
10
+ var Cipher = javax . crypto . Cipher ;
11
+ var KeyGenerator = javax . crypto . KeyGenerator ;
12
+ var KeyProperties = android . security . keystore . KeyProperties ;
13
+ var SecretKey = javax . crypto . SecretKey ;
14
+ var KeyGenParameterSpec = android . security . keystore . KeyGenParameterSpec ;
15
+
16
+
17
+ //var FingerprintManager;
18
+
19
+ //var KEYGUARD_SYSTEM_SERVICE = "keyguard";
20
+ var KEY_NAME = 'fingerprintscanner' ;
21
+ var SECRET_BYTE_ARRAY = Array . create ( 'byte' , 16 ) ;
22
+ var REQUEST_CODE_CONFIRM_DEVICE_CREDENTIALS = 1 ;
23
+ var AUTHENTICATION_DURATION = 15 ; // in seconds
24
+
25
+ var activity = null ;
26
+
27
+ var keyguardManager = null ;
28
+
29
+ var title = null ;
30
+ var message = null ;
31
+
32
+ var available = function ( ) {
33
+ return new Promise ( function ( resolve , reject ) {
34
+
35
+ keyguardManager = utils . ad . getApplicationContext ( ) . getSystemService ( "keyguard" ) ;
36
+
37
+ if ( ! keyguardManager . isKeyguardSecure ( ) ) {
38
+ resolve ( false ) ;
39
+ return ;
40
+ }
41
+
42
+ if ( android . os . Build . VERSION . SDK_INT >= 23 ) { //23 == android.os.BUILD.M
43
+ //Fingerprint API only available on from Android 6.0 (M)
44
+ var fingerprintManager = utils . ad . getApplicationContext ( ) . getSystemService ( "fingerprint" ) ;
45
+ if ( ! fingerprintManager . isHardwareDetected ( ) ) {
46
+ // Device doesn't support fingerprint authentication
47
+ reject ( 'Device doesn\'t support fingerprint authentication' ) ;
48
+ } else if ( ! fingerprintManager . hasEnrolledFingerprints ( ) ) {
49
+ // User hasn't enrolled any fingerprints to authenticate with
50
+ reject ( 'User hasn\'t enrolled any fingerprints to authenticate with' ) ;
51
+ } else {
52
+ resolve ( true ) ;
53
+ }
54
+ } else {
55
+ reject ( 'Your api version don\'t support fingerprint auth' ) ;
56
+ }
57
+
58
+ resolve ( true ) ;
59
+ } ) ;
60
+ } ;
61
+
62
+ var didFingerprintDatabaseChange = function ( ) {
63
+ return new Promise ( function ( resolve , reject ) {
64
+ resolve ( 'Not yet implemented!' ) ;
65
+ } ) ;
66
+ } ;
67
+
68
+
69
+ var verifyFingerprint = function ( arg ) {
70
+ if ( arg ) {
71
+ if ( arg . title ) title = arg . title ;
72
+ if ( arg . message ) message = arg . message ;
73
+ }
2
74
return new Promise ( function ( resolve , reject ) {
3
- resolve ( false ) ;
75
+ activity = app . android . foregroundActivity ;
76
+ try {
77
+ activity . onActivityResult = function onActivityResult ( requestCode , resultCode , data ) {
78
+ if ( requestCode === REQUEST_CODE_CONFIRM_DEVICE_CREDENTIALS ) {
79
+ if ( resultCode === android . app . Activity . RESULT_OK ) {
80
+ // the user has just authenticated via the ConfirmDeviceCredential activity
81
+ resolve ( 'Congrats! You have just been authenticated successfully!' ) ;
82
+ } else {
83
+ // the user has quit the activity without providing credentials
84
+ reject ( 'The last authentication attempt was cancelled.' ) ;
85
+ }
86
+ }
87
+ } ;
88
+
89
+ if ( keyguardManager == null ) {
90
+ reject ( 'Sorry, your device does not support keyguardManager.' ) ;
91
+ }
92
+ if ( keyguardManager && ! keyguardManager . isKeyguardSecure ( ) ) {
93
+ reject ( 'Secure lock screen hasn\'t been set up.\n Go to "Settings -> Security -> Screenlock" to set up a lock screen.' ) ;
94
+ }
95
+
96
+ createKey ( ) ;
97
+ tryEncrypt ( ) ;
98
+
99
+ } catch ( ex ) {
100
+ console . log ( "Error in verifyFingerprint: " + ex ) ;
101
+ reject ( ex ) ;
102
+ }
4
103
} ) ;
5
104
} ;
6
105
7
- // shouldn't be called anyway because 'available' returned false
8
- exports . verifyFingerprint = function ( ) {
106
+
107
+ var verifyFingerprintWithCustomFallback = function ( arg ) {
9
108
return new Promise ( function ( resolve , reject ) {
10
- reject ( "Not available" ) ;
109
+ try {
110
+ resolve ( 'Not implemented' ) ;
111
+ } catch ( ex ) {
112
+ console . log ( "Error in verifyFingerprint: " + ex ) ;
113
+ reject ( ex ) ;
114
+ }
11
115
} ) ;
12
- } ;
116
+ } ;
117
+
118
+ /**
119
+ * Creates a symmetric key in the Android Key Store which can only be used after the user has
120
+ * authenticated with device credentials within the last X seconds.
121
+ */
122
+ function createKey ( ) {
123
+ try {
124
+ var keyStore = KeyStore . getInstance ( 'AndroidKeyStore' ) ;
125
+ keyStore . load ( null ) ;
126
+ var keyGenerator = KeyGenerator . getInstance ( KeyProperties . KEY_ALGORITHM_AES , 'AndroidKeyStore' ) ;
127
+
128
+ keyGenerator . init (
129
+ new KeyGenParameterSpec . Builder ( KEY_NAME , KeyProperties . PURPOSE_ENCRYPT | KeyProperties . PURPOSE_DECRYPT )
130
+ . setBlockModes ( [ KeyProperties . BLOCK_MODE_CBC ] )
131
+ . setUserAuthenticationRequired ( true )
132
+ . setUserAuthenticationValidityDurationSeconds ( AUTHENTICATION_DURATION )
133
+ . setEncryptionPaddings ( [ KeyProperties . ENCRYPTION_PADDING_PKCS7 ] )
134
+ . build ( )
135
+ ) ;
136
+ keyGenerator . generateKey ( ) ;
137
+ } catch ( error ) {
138
+ // checks if the AES algorithm is implemented by the AndroidKeyStore
139
+ if ( ( error . nativeException + '' ) . indexOf ( 'java.security.NoSuchAlgorithmException:' ) > - 1 ) {
140
+ //You need a device with API level >= 23 in order to detect if the user has already been authenticated in the last x seconds.
141
+ }
142
+ }
143
+ }
144
+
145
+
146
+ function tryEncrypt ( ) {
147
+ try {
148
+ var keyStore = KeyStore . getInstance ( 'AndroidKeyStore' ) ;
149
+ keyStore . load ( null ) ;
150
+ var secretKey = keyStore . getKey ( KEY_NAME , null ) ;
151
+
152
+ var cipher = Cipher . getInstance ( KeyProperties . KEY_ALGORITHM_AES + "/" +
153
+ KeyProperties . BLOCK_MODE_CBC + "/" +
154
+ KeyProperties . ENCRYPTION_PADDING_PKCS7 ) ;
155
+
156
+ cipher . init ( Cipher . ENCRYPT_MODE , secretKey ) ;
157
+ cipher . doFinal ( SECRET_BYTE_ARRAY ) ;
158
+
159
+ return true ;
160
+ } catch ( error ) {
161
+ if ( ( error . nativeException + '' ) . indexOf ( 'android.security.keystore.UserNotAuthenticatedException' ) > - 1 ) {
162
+ // the user must provide their credentials in order to proceed
163
+ showAuthenticationScreen ( ) ;
164
+ } else if ( ( error . nativeException + '' ) . indexOf ( 'android.security.keystore.KeyPermanentlyInvalidatedException' ) > - 1 ) {
165
+ //Invalid fingerprint
166
+ console . log ( error ) ;
167
+ } else {
168
+ console . log ( error ) ;
169
+ }
170
+
171
+ return false ;
172
+ }
173
+ }
174
+
175
+ /**
176
+ * Starts the built-in Android ConfirmDeviceCredential activity.
177
+ */
178
+ function showAuthenticationScreen ( ) {
179
+ // title and description are optional, if you want the defaults,
180
+ // you must pass nulls to the factory function
181
+
182
+ if ( title === null ) title = 'Please confirm your credentials.' ;
183
+ if ( message === null ) message = 'We are doing this for your own security.' ;
184
+ var intent = keyguardManager . createConfirmDeviceCredentialIntent ( title , message ) ;
185
+
186
+ if ( intent != null ) {
187
+ activity . startActivityForResult ( intent , REQUEST_CODE_CONFIRM_DEVICE_CREDENTIALS ) ;
188
+ }
189
+ }
190
+
191
+
192
+
193
+ exports . available = available ;
194
+ exports . didFingerprintDatabaseChange = didFingerprintDatabaseChange ;
195
+ exports . verifyFingerprint = verifyFingerprint ;
196
+ exports . verifyFingerprintWithCustomFallback = verifyFingerprintWithCustomFallback ;
0 commit comments