mibrito707 / cordova-plugin-secure-storage-echo

Secure storage plugin for Apache Cordova
MIT License
73 stars 73 forks source link

Key Not found error throws in ionic app - when we launch the app second time #30

Closed sankaryg closed 4 years ago

sankaryg commented 4 years ago

Error in ionic app with android platform: For the first time it works but after some time killing and restarting the app will fails. Getting error like key not found.

vendor.js:1823 ERROR Error: Uncaught (in promise): Error: Key [xyz] not found. Error: Key [xyz] not found. at fail (securestorage.js:42) at Object.callbackFromNative (cordova.js:293) at processMessage (cordova.js:1114) at processMessages (cordova.js:1137) at t.invoke (polyfills.js:3) at Object.onInvoke (vendor.js:5134) at t.invoke (polyfills.js:3) at r.run (polyfills.js:3) at polyfills.js:3 at t.invokeTask (polyfills.js:3) at c (polyfills.js:3) at c (polyfills.js:3) at polyfills.js:3 at t.invokeTask (polyfills.js:3) at Object.onInvokeTask (vendor.js:5125) at t.invokeTask (polyfills.js:3) at r.runTask (polyfills.js:3) at o (polyfills.js:3)

kbrin423 commented 4 years ago

Same here: Error: Key [loginInfo] not found. at fail (securestorage.js:42) at Object.callbackFromNative (cordova.js:293) at processMessage (cordova.js:1114) at processMessages (cordova.js:1137) at t.invoke (polyfills.js:3) at Object.onInvoke (vendor.js:4656) at t.invoke (polyfills.js:3) at r.run (polyfills.js:3) at polyfills.js:3 at t.invokeTask (polyfills.js:3) at Object.onInvokeTask (vendor.js:4647) at t.invokeTask (polyfills.js:3) at r.runTask (polyfills.js:3) at o (polyfills.js:3)

//---------------

Ionic:

Ionic CLI : 5.4.1 Ionic Framework : ionic-angular 3.9.5-201905161949 @ionic/app-scripts : 3.2.4

Cordova:

Cordova CLI : 8.0.0 Cordova Platforms : android 7.1.0, ios 4.5.5 Cordova Plugins : cordova-plugin-ionic-keyboard 2.2.0, cordova-plugin-ionic-webview 1.2.0, (and 36 other plugins)

Utility:

cordova-res : 0.6.0 (update available: 0.8.1) native-run : 0.2.8 (update available: 0.3.0)

System:

ios-deploy : 1.9.2 NodeJS : v10.16.0 (/Users/brin/.nvm/versions/node/v10.16.0/bin/node) npm : 6.13.0 OS : macOS Catalina Xcode : Xcode 11.3 Build version 11C29

-> Simulator : PIXEL 3 API 29

mcendon commented 4 years ago

Same problem with key not found here. Tested on API 23, API 28, API 29 android simulators with the same result.

On real device API 28 it works fine

Ionic:

ionic (Ionic CLI) : 4.12.0 (/Users/mauro/.nvm/versions/node/v8.11.3/lib/node_modules/ionic) Ionic Framework : ionic-angular 3.9.2 @ionic/app-scripts : 3.1.11

Cordova:

cordova (Cordova CLI) : 8.0.0 Cordova Platforms : android 8.0.0, ios 4.5.5 Cordova Plugins : cordova-plugin-ionic-keyboard 2.1.3, cordova-plugin-ionic-webview 4.1.3, (and 30 other plugins)

System:

ios-deploy : 1.9.4 NodeJS : v8.11.3 (/Users/mauro/.nvm/versions/node/v8.11.3/bin/node) npm : 6.12.0 OS : macOS Catalina Xcode : Xcode 11.0 Build version 11A420a

12-24 13:51:24.369 17826 17826 D SystemWebChromeClient: http://localhost/build/main.js: Line 418 : Error: Key [fngpTkn] not found.
12-24 13:51:24.370 17826 17826 I chromium: [INFO:CONSOLE(418)] "Error: Key [fngpTkn] not found.", source: http://localhost/build/main.js (418)
sankaryg commented 4 years ago

Issue reproducible in Android devices

As per my understanding, figured out the root cause for the issue: In SecureStorage.Java:

When we create an object it goes it into "init" action and generating the encryption keys using this method: generateEncryptionKeys(userAuthenticationValidityDuration);

private void generateEncryptionKeys(Integer userAuthenticationValidityDuration) {
    if (generateKeysContext != null && !generateKeysContextRunning) {
        cordova.getThreadPool().execute(new Runnable() {
            public void run() {
                generateKeysContextRunning = true;
                try {
                    String alias = service2alias(INIT_SERVICE);
                        //Solves Issue #96. The RSA key may have been deleted by changing the lock type.
                        getStorage(INIT_SERVICE).clear();
                        RSA.createKeyPair(getContext(), alias, userAuthenticationValidityDuration);
                        generateKeysContext.success();
                } catch (Exception e) {
                    Log.e(TAG, MSG_KEYS_FAILED, e);
                    generateKeysContext.error(MSG_KEYS_FAILED + e.getMessage());
                } finally {
                    generateKeysContext = null;
                    generateKeysContextRunning = false;
                }
            }
        });
    }
}

this method is creating the keys and stored the key value pair in preferences with encrypted format.

But if I kill and relaunch my android app, it should fetch the associated keys with decrypted value. In the second time it again goes to init method and clearing the keys and generating the encryption keys again. Every time if i kill and relaunch, code gone into init action and clearing the keys because of this code: getStorage(INIT_SERVICE).clear();

To make it work temporarily added a small change in code:

private void generateEncryptionKeys(Integer userAuthenticationValidityDuration) {
    if (generateKeysContext != null && !generateKeysContextRunning) {
        cordova.getThreadPool().execute(new Runnable() {
            public void run() {
                generateKeysContextRunning = true;
                try {
                    String alias = service2alias(INIT_SERVICE);
                    Map<String, ?> map = getStorage(INIT_SERVICE).getPrefs().getAll();
                    if(map.size() == 0){
                        //Solves Issue #96. The RSA key may have been deleted by changing the lock type.
                        getStorage(INIT_SERVICE).clear();
                        RSA.createKeyPair(getContext(), alias, userAuthenticationValidityDuration);
                    }
                       generateKeysContext.success();
                } catch (Exception e) {
                    Log.e(TAG, MSG_KEYS_FAILED, e);
                    generateKeysContext.error(MSG_KEYS_FAILED + e.getMessage());
                } finally {
                    generateKeysContext = null;
                    generateKeysContextRunning = false;
                }
            }
        });
    }
}

Let me know if it works for you.

murphy1312 commented 4 years ago

Not sure if your code really fixes the issue. It does remove the Key Not found error but now I got: Error: User changed or deleted their auth credentials on each start, after changing the screen lock type once.

The generateEncryptionKeys method being called on every start means that encryptionKeysAvailable(alias) is not working? So maybe that should be fixed.

Or it could be that the call in encryptionKeysAvailable(alias)->RSA.isEntryAvailable() which uses keyInfo.isInsideSecureHardware() simply does not work on my emulator (android 10).

Zach-Attach commented 4 years ago

I've been having the same issue. Are there any updates or workarounds for this issue? The solution suggested by @sankaryg did not work for me.

Zach-Attach commented 4 years ago

Update: I figured out what was wrong with the solution listed by @sankaryg and went ahead and created a PR for the fix. The problem was that the getPrefs() method did not exist in SharedPreferencesHandler.java and java.util.Map needed to be imported into SecureStorage.java.

CaioMelo8 commented 4 years ago

@Zach-Attach using your PR did the trick in the project I'm working on, Thanks, man!

I really hope this can be merged in this repo.

Zach-Attach commented 4 years ago

https://github.com/mibrito707/cordova-plugin-secure-storage-echo/pull/41

mread1208 commented 4 years ago

Yup, also confirming this fixed our Android issue. Thanks @Zach-Attach ! +1 to get this merged and released at some point.

mibrito707 commented 4 years ago

Thanks for the contribution @Zach-Attach Per merged and released in v5.1.0

zarko-tg commented 4 years ago

It's possible that I am experiencing an issue with "Error: User changed or deleted their auth credentials" despite using the latest plugin version. Don't have a full understanding of the case yet but it seems that the plugin ends up malfunctioning over and over if the screen lock has been disabled, then set again. I've seen this on both Android 10 emulator and a Samsung device with Android 9.

A62-MaMi-46 commented 4 years ago

@zarko-tg I ran into the same problem...did you already figured it out?

My scenario:

Fingerprint is enabled -> I create my namespace and save my data into the secure storage -> bring the app into the background -> settings -> remove my security features -> focus the app -> remove the previously data -> bring it into the background -> settings -> set a new fingerprint -> focus on the app again -> write new data in my secure storage and get the following error inside my console:

java.security.UnrecoverableKeyException: User changed or deleted their auth credentials

zarko-tg commented 4 years ago

@A62-MaMi-46 No, I more or less gave up since this issue renders the plugin useless on Android. And it doesn't seem to be any good alternative.

mread1208 commented 4 years ago

@zarko-tg, @A62-MaMi-46 My issues were all resolved with the latest version (and this PR). Is it possible there's something with your front-end code that's not storing the data properly?

Have you tried to use some simpler logic? Maybe try storing some dummy data, then retrieving it just to ensure it's not an issue with the plugin, but rather with the way you're using it. Any code samples could help debug the issue too.