mjwheatley / cordova-plugin-android-fingerprint-auth

A cordova plugin for fingerprint authentication using the hardware fingerprint scanner on devices running Android 6+
Apache License 2.0
168 stars 131 forks source link

Update plugin to encrypt and decrypt clientSecret #38

Closed simone-compagnone closed 7 years ago

simone-compagnone commented 7 years ago

We read about issue #5 and we updated the plugin with encrypt and decrypt features.

Now the usage flow is a bit different:

FabrizioBrancati commented 7 years ago

This update doesn't work as the previous version, because now the show function decrypt the clientSecret, but you can call it to just check that fingerprint is valid (like before).

We suggest you to bumping version to 1.0.0 and please create a tag.

mjwheatley commented 7 years ago

First off, WELL DONE!
I've been trying to do this myself but ran into trouble with IvParameterSpec. Testing your branch I was able to successfully encrypt and decrypt the clientSecret.

However I ran into the following problem. clientSecret1 = "aSecret" clientSecret2 = "aVerySecretSecret"

FingerprintAuth.init({clientSecret: clientSecret1}) returns encryptedToken1. // Yeah! FingerprintAuth.show({clientSecret: encryptedToken1}) returns clientSecret1. // Success! Hurray!

FingerprintAuth.init({clientSecret: clientSecret2}) returns encryptedToken2. // Yeah!

Here's the problem: FingerprintAuth.show({clientSecret: encryptedToken1} // :( "errorCallback(): Failed to encrypt the data with the generated key: BadPaddingException: javax.crypto.BadPaddingException"

FingerprintAuth.show({clientSecret: encryptedToken2} // Success!

SCENARIO This plugin is integrated into an app for the purpose of user authentication. User1 and User2 share a device and both use this application.

User1 signs in and enrolls a fingerprint by passing username:password as the clientSecret to FingerprintAuth.init() and the plugin returns encryptedToken1. The application stores this token under User1's profile. Subsequently, User1 attempts to sign into the app using username and enrolled fingerprint. The app queries for the username to retrieve the encrypted token. The app then passes the encrypted token as the clientSecret for FingerprintAuth.show() and receives the decrypted credential string (username:password). The application can then use these credentials to sign in the user.

User2 goes through the same process. Given the above error, User1's token would no longer be able to be decrypted and would not be able to sign in using a fingerprint. *End scenario

The initCipher() method has always been a trouble maker. I believe the issue is because you are only storing a single cipherIV in the shared prefs. So when User2 enrolls, you lose User1's cipherIV and when User1 tries to authenticate User2's cipherIV is being used to decrypt User1's token.

In my attempt I got rid of the clientSecret and added parameters for username, password, token, and cipherMode. Then you could use a single action as I did previously FingerprintAuth.show() and use the parameters to determine encrypt or decrypt. In this way you could pass username, password, and cipherMode: "encrypt" to create the credential string (username:password) and use the username as the key for the cipherIV. On subsequent authentication you would pass the username, token, and cipherMode: "decrypt" and use the username to retrieve the cipherIV from the shared prefs and use that to decrypt the token, parse the credential string, and return a JSON object containing keys for username and password.

I'll go ahead and give this a try and report back.

FabrizioBrancati commented 7 years ago

We choose to create a separated function (init) to don't add a cipherMode parameter, that it can be not written well. The developer has to call the init when the user activate the fingerprint and the show to really use it to enter into the App. However we can edit show function to add a cipherMode parameter.

To add multiple user support, we have to edit the delete function to delete data of only one user, and I suggest to add a reset function, to remove all data (Key and IV).

mjwheatley commented 7 years ago

Ok, that worked well. I will work on merging the changes.

FabrizioBrancati commented 7 years ago

So we have to update the plugin to support multiple user and then you will merge? 😄

mjwheatley commented 7 years ago

Merged, updated, and released new version 1.1.0

mjwheatley commented 7 years ago

Fixes Issue #5

FabrizioBrancati commented 7 years ago

Wow, great! 👍 Please consider creating a tag 😄

mjwheatley commented 7 years ago

Created tag v1.1.0

simone-compagnone commented 7 years ago

Great work!! 😀😀

simone-compagnone commented 7 years ago

Also you can considered multilogin optional for the plugin. So you can use clientId (required) + username (optional, empty string for null value) to save the shared preference. The Key for the shared preference is clientid+username and the encrypt string is clientid+username+":"+password. In this way the multilogin is optional and not required, the developer can choose to use or not.