I'm trying to achieve the following through Worklight.
- My app has two sets of features. One set of features can be accessed only when the app is connected to the server and the user is authenticated. Another set of features can be accessed offline but they require data from an encrypted JSONStore.
- I have a JSONStore on the client device which is initialized using a password. Therefore, the data in the store will be encrypted. Also, this JSONStore is synced to a database on the server through an adapter.
- I have also setup another adapter which authenticates the user by using another set of credentials stored in a database. The user can be authenticated only when the app is online.
What I want to do is to unify these two approaches so that the user needn't enter two sets of credentials to access these two different sets of features. One possible solution that came to my mind is just to encrypt the JSONStore and perform the adapter authentication without the intervention of the user. But I don't think that it's secure.
Any advice or approach to solve this issue?
The following is just an idea, I'm not a security expert.
Requirements:
- To use the offline features you must have been online and authenticated at least one time.
- Your application must have an login view to input some credentials (e.g. username/email and password).
Steps:
- First time the user inputs the correct credentials and successfully authenticates with the server: hash the credentials. For example:
var myHash = md5(loginField.getUser() + loginField.getPassword())
. You can find md5 JavaScript libraries on Github.
- Use that hash to initialize the store. For example:
WL.JSONStore.init(..., {password: myHash})
.
- Send the hash to the backend over HTTPS, you will need it if the user changes his/her credentials. No need to save the credentials or the hash on the device (
loginField = null; myHash = null
). Alternatively, you could just generate the hash on the server and store it, without having the client send it back, just make sure both client and server are using the same hashing algorithm.
- When working offline, ask the user for his/her credentials, hash them and use it to access data inside the store.
- If the user changes his/her credentials (e.g. via the web interface for your application), the hash will be different and store won't init. However, the user should've successfully authenticated with the server with the new/valid credentials. Ask the server for the old hash, init the store with the old hash, and change the password to init the store to the new hash based on the new/valid credentials. For example:
WL.JSONStore.changePassword(oldHash, newHash)
.
Optional: You may want to consider using a salt. For example: var salt = Math.random(), myHash = md5(loginField.getUser() + loginField.getPassword() + salt)
.
You will need to store the salt somewhere so you can re-generate the hash once the user returns to the application. You should be able to init another unencrypted store to persist it. For example WL.JSONStore.init(..., {username: 'metadata'}).then(function(){/*add salt to store*/})
. More information regarding using two stores here.