2

Got a weird one here. JSONStore in Worklight 6.1.0.01 on iOS 7.1 seems to be arbitrarily rejecting some passwords.

Here's the code we are using to initialize the JSONstore:

var bitArray = sjcl.hash.sha256.hash(username + ':'+ password);
var digest_sha256 = (sjcl.codec.hex.fromBits(bitArray));

options.username = username
options.password = digest_sha256;

options.localKeyGen =  true;
options.clear = false;
collections[this.collection1] = collection1;
collections[this.collection2] = collection2;
collections[this.collection3] = collection3;

WL.JSONStore.init(collections, options).then(function() {
    onSuccess();
}).fail(function(errorObject) {
    onFailure();
});

I've got a user: ad1tst password: The output of the sha256 hash for this user is b5de1dfbbd09c5f8cf78d858eb4ed09e3b9826f9c35c950d164e8accf7775082

Using this hash as a password, the user can initialize the database.

I've got another user ad2tst password: The output of the sha256 has for this user is 607c04ef944b36ec939d39f7c6b24757776918b8425e5a3b912738d6dea0ebea

Using this hash as a password this user cannot initialize the database.

If the user ad2tst uses the password (which gives a hash of 1feff7f75cfd73fc796d9dd612261b3f72f4292ce76ae3a5e92f7b1dbb2fd038) the user can initialize the database.

This problem is not restricted to just these 2 test users. We have live users that are exhibiting the same problems.

We are getting the following error from the JSONStore runtime:

__33-[JsonStoreQueue setDatabaseKey:]_block_invoke [Line 128] Invalid password
2014-05-16 16:39:26.611 Audits[865:60b] THREAD WARNING: ['StoragePlugin'] took '71.429932' ms. Plugin should use a background thread.
2014-05-16 16:39:26.612 Audits[865:60b] [ERROR] [wl.jsonstore] {"src":"initCollection","err":-3,"msg":"INVALID_KEY_ON_PROVISION","col":"collection1","usr":"ad2tst","doc":{},"res":{}}

The INVALID_KEY_ON_PROVISION error is being generated by the 'provision' method of the JSONStore plugin somewhere deep in the bowels of Worklight's native code.

In follow-on to one attempted answer below; each run of the app is done on a clean install. The test cycle is:

  1. Install app
  2. Run with one of the test users
  3. Watch it fail or pass, depending on which username/password pair is supplied
  4. Delete the app
  5. Goto step 1

So, this is not a situation where the database is already encrypted with another password.

Idan Adar
  • 44,156
  • 13
  • 50
  • 89
Jack Cox
  • 3,290
  • 24
  • 25

2 Answers2

1

Invalid key on provision means that you encrypted the store with one password first, then tried to open it with another (wrong) password.

Make sure you are using a different username, or destroying the store first, before trying to use a new password.

If you destroy the store, and then use the other password, it should work with it.

Daniel A. González
  • 1,225
  • 8
  • 11
  • 1
    In the case of the defect above, each run was done on a clean application that had just been installed so there is no prior copy of the jsonstore database. The test cycle being: 1) Install app, 2) run with one of the test users, 3) watch it fail or watch it pass, 4) delete the app, 5) repeat step 1. So, while your point is valid, it does not apply in this case. – Jack Cox May 17 '14 at 02:18
  • Actually, it could still be the case, depending on what you mean by clean application. If you deleted the older application and installed the new one without calling destroy in either case, and without clearing the keychain, it will still have the key stored for that application if you used the same username. That is because the iOS keychain is not cleared after you delete the application. It is an unlikely situation, but it could be what is happening here. If this is not the case, then it is something that we will have to try and reproduce. – Daniel A. González May 18 '14 at 02:42
  • Daniel: I guess that's a question for the folks at IBM, is WL storing passwords in the keychain? Also, having to call destroy, while a workaround, isn't very clean because the user can delete the app at anytime without the app's knowledge. So, the app would always need to check for first-run on a device and if it's the first run, destroy JSONstore just in case it's not actually the first run of the app on the device. – Jack Cox May 18 '14 at 11:27
  • Yes, security artifacts (not the password itself, but related to the password) is stored in the keychain. It seems that it is a defect. Can you confirm that this is what is happening? – Daniel A. González May 19 '14 at 13:01
  • 1
    We've resolved the problem by keeping a user preference that indicates whether the app has launched before. If the app hasn't launched before (but there may be cruft in the keychain) then we run WL.JSONStore.destroy(). In the success promise of the destroy we initialize the database. This appears to work, but it does generate a spurious warning about no DPK document. – Jack Cox May 19 '14 at 15:41
1

If you have questions, StackOverflow is a great place to get answers. However, for bug reports I suggest opening a PMR. If you're looking for a new feature I suggest opening a feature request. This is not the right place to deal with those two issues.

There are a couple of things that I want to point out:

Unlike Android, which uses Shared Preferences to persist the encrypted data protection key (DPK). iOS uses the Keychain instead. Among the differences, the data in Shared Preferences gets removed when the application is uninstalled. Data in the keychain is not removed when the application is uninstalled, unless additional steps are taken. Here's an answer that shows how one might clear the keychain when the application is re-installed. I believe there's a Worklight Hybrid API for working with NSUserDefaults that is documented here. I haven't really used it, so your millage may vary. The use of Shared Preferences and the Keychain for JSONStore is documented here.

I presume your problem will be fixed (or at least mitigated) if you always call the JSONStore destroy API every time the application is re-installed, that way you would get the same behavior Android exhibits. You can work with various users using the same application if you call the closeAll API before calling the init API with a new username and password. The changePassword API will update the password used to access the contents in a store.

I made a new QUnit test based on your question, take a look here. The idea is to open a store with one user+pass, add, find and close. Then open another store with another user+pass, add, close, open again and find the data that was stored. Said test case is passing on iOS 7.1 using Worklight v6.1. Notice I used your input for the usernames and passwords:

  • ad1tst + b5de1dfbbd09c5f8cf78d858eb4ed09e3b9826f9c35c950d164e8accf7775082
  • ad2tst + 607c04ef944b36ec939d39f7c6b24757776918b8425e5a3b912738d6dea0ebea

Just to reiterate what my answer is:

  • Open a PMR if you wish to report an issue. I'm hoping my suggestion above will fix it, but it could be something else that's broken and I misunderstood the issue.
  • Open a feature request if you want a better API to handle a specific user scenario. I think the use case presented is valid and this is worth pursuing.
Community
  • 1
  • 1
cnandreu
  • 5,113
  • 3
  • 25
  • 50