Worklight Online + Offline Authentication - ibm-mobilefirst

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.

Related

SailsJS secure authentication

I am building app using SailsJS as backend and angular as frontend. On many websites I have found that auth is done by setting req.session.userID to som value but then in policy it only performs basic check like if(req.session.userID) but I am not sure that this is secure. What if I put some random string to my cookie named userID will system consider this as valid login?
For example my correct userID is ABCDEF but what if some attacker come by and he sets his cookie userID to DEFGH. Will system consider this as valid login? I don't think that there is some background validation against database going on. Wouldn't it be better to create model called Sessions which will store randomly generated session ID and associated userID? Then the system at user login would generate random sessionID which will be stored in DB and in policy system will check if currently set req.session.sessionID is valid.
I am asking this because I don't have very deep understanding of sails but from my point of view solution proposed in documentation doesn't seem secure.
I recommend that you take a look at JWT and how it solves some problems. Then another problem will be "how to store this token". And that you can solve with cookies, local storage, etc. all depending on your needs and possibilities. Usually a local storage + middleware in the client side with reddis on the server side (advanced session behavior) is enough.

Is using Laravel api_token authentication not like storing password in plain text?

I want to validate my RESTful API using token authentication. Two key options provided are https://github.com/tymondesigns/jwt-auth and Laravel's own inbuilt token authentication.
I'm unable to make jwt-auth work for me even if it looks the most promising, so I decide to check on Laravel's implementation.
It is pretty straightforward. Create an extra field api_token in users DB, generate a random string and store it against the users record IN PLAIN TEXT, then any request the user sends they should append the api_token, which you shall authenticate by checking its existence in the DB. Just that.
Isn't that like storing passwords in plain text because anyone who happens to have access to the DB is as good as authenticated? Isn't there an outright security risk there? Someone help me understand this one.
Also, how does one handle things like invalidating the token, giving the token an expiry period, and such?
for Similar Case I am not using any external plugin, while Laravel already ship a project called Lumen which is best suitable for Restfull web service,
I am storing the encrypted hash string as api_token in the user table,
and in my mobile application i let the users authenticate by username password first time and then i store the decrypted token in the mobile to maintain the user state for subsequent api calls, key point is i am storing the decrypted user token in the mobile and whenver i receive the token in server, i do comparison to match both of them using the same encryption function i have used before,...
in this case you have to come up with your own encryption algorithm since you need to use the same algorithm to decry-pt in the client,
or else an easy way is to copy the user password hash string in the api_token field and store the user password in the client side,
but you have to make sure the security of the client application,
if you consider native android, i will use sharedpreference in private mode which is secure....
if(Hash::check($password,$user->password)){
$response['success'] = 1;
$response['message'] = 'You have Connected to Server Successfully';
$response['api_token'] = $user->api_token;
}else{
$response['success'] = 0;
$response['message'] = 'Authentication Unsuccessful';
$response['api_token'] = '';
}

How to store encryption key/password in JSONStore

I am using JSONStore to store some data in my project but my problem is that I want to store a key that is used to unlock the data.
Does MobileFirst provide any way to
Securely store a key at client side or server side.
Is there any way that I can get the key from adapter or unlock the
JSONStore by connecting to adapter.
I believe you want to encrypt the data inside of a JSONStore collection and at the same time you want to be able to decrypt the collection without requiring the user to enter a password.
Approach 1: Client side
If you want to accomplish that in iOS you could use Touch ID for that purpose. You could read up more on that by going to https://www.ibm.com/support/knowledgecenter/SSHS8R_7.1.0/com.ibm.worklight.dev.doc/devref/t_setting_up_touch_id_jsonstore.html
For Android there is no out-of-the box integration but staring in Android Marshmallow (6.0) there is an API for the fingerprint scanner which you could also use. https://developer.android.com/about/versions/marshmallow/android-6.0.html#fingerprint-authentication
Basically with the approach mentioned above you are creating a random password and storing it securely in the device. Then the device prompts the user with the authentication (fingerprint scanner or pin code) and then if it's successful you will get access to that random password.
Approach 2: Server side
In this approach you will use an adapter to hash a token/string sent from the client. For this to work you will need to use something that remains constant i.e., device id WL.Device.getID() https://www.ibm.com/support/knowledgecenter/SSHS8R_7.1.0/com.ibm.worklight.apiref.doc/html/refjavascript-client/html/WL.Device.html#getID
app.js
WL.Device.getID(function(response){
var id = response.deviceID;
var req = WLResourceRequest('/adapters/Util/hash', WLResourceRequest.POST);
return req.sendFormParameters({
pass: id
});
}).then(function(response){
var passwordHash = response.responseJSON.hash;
// open JSONStore collection with the passwordHash
});
In your adapter you can hash your password/device id then return it to the device to open the JSONStore collection. You can check the following post How can I hash a password in Java? if you want to hash passwords in your Java adapter
This approach is a bit tricky since you will need to authenticate the somehow to make sure you are only opening/decrypting JSONStore for the legitimate user.

Custom RESTful API Authentication

I was just wondering if this would be a reasonable way to write a custom authentication method for a RESTful API. It seems moderately secure, but perhaps I'm way wrong here.
1) Email and Password are sent over HTTPS to my server.
2) Server stores the email, and runs the password through a SHA512 hash with a 256 bit random salt. The hashed and salted password is stored in the database.
So now we have:
email = email#example.com
password = OHqhuewQclakufEjUbZMbowJKEGcvEBz,51c6a3cb58e10754f76e334de064a9dede7875141e1ce0233e3ff14fd7be98a4d5b8fc1c5ab871cb3b1d6b0c9f8073bc3558308511fc4fd6bd049aed5e58a9a4
3) Generate a random token with a lifetime (very random and large), store it the database, and then link that random token to that specific authenticated user.
4) I send the token back to the client through HTTPS (web, Android, or iOS), whereby it's stored in cookies or SharedPrefs or what have you.
5) Now, the client sends the token with every request. The server can then check the cached token value with the one it's receiving each time to make sure that the server always knows who's making requests.
Does this seem reasonable and secure? The issue I think that arises here is if the tokens data becomes compromised. Is there perhaps anyway to toughen that one part up?
you must know that there is nothing 100% secure,
you can store the ip of the user recent logged, if you receive another login from the same user from diferent ip, you can send back a response indicating that user is already connected

Can I Firebase createUser with an arbitrary ID instead of an email address

I'm using Firebase for an Atlassian Connect AddOn. I want to use Firebase users to secure the data.
The users will be identified by a clientKey provided by Atlassian (probably after I fudge it a bit) - NOT BY EMAIL.
Ideally, I don't want to have to do my own authentication here, as the Firebase.createUser method would suffice entirely if I could provide something other than an email to it, but I can't find anything like that in the documentation.
Is there a way I can create Firebase users WITHOUT AN EMAIL (just an ID and password), without going to all the way into oAuth and all that jargon to create my own custom authentication?
A Firebase user must have an email. If that is a problem then we can't use a Firebase "user", but instead a "token" (which must have a UID as part of it's payload and hence behaves the same way in terms of security once it reaches their datastore).
If you don't need a password, then "instead of double-authenticating and duct taping" as #Kato kindly pointed out, you can generate your own Firebase tokens and serve them to the client.
If you require the user to provide a password then you'd have to implement your own verification before you generate the token and serve it to the client. Since there's no Firebase user involved anymore, but rather a token your privileged server can arbitrarily create and serve, it's your responsibility to ensure you're doing that at the right time (i.e. when a user has provided your server with an adequate ID and password).
Read more about Custom Authentication here and tokens.