0

I've been reading a lot of threads and decided to to post my conclusion before going on coding. I've found a lot of interesting things (What is the most appropriate way to store user settings in Android application) and this is what I have gathered so far :

We'll suppose that https is always used.

By "remember me", I mean the following : the user will never authenticate on the app ever again because it would annoy him to authenticate even once a week.

When not using a "remember me" feature : Oauth2 is the way to go, exchange tokens are used -> nothing gets stored, most secure

When using a "remember me" feature :

Upon first Register/user/login usage of the app : Password is hashed by server with its own "private key"/hash and returned to android.

This hashed password is then encrypted before being stored inside SharedPreferences. Given the Hashed password never expires, we now have the following caveats :

  • If the phone is lost/rooted, only this hash can be retrieved to access user's data on the server : user's data is compromised.
  • The crypting key is stored inside code which can be decompiled : : user's data is also compromised. Since attacker can uncrypt the hashed password and use it.

Conclusion : Using a "remember me" feature, while handy for the user, makes it vulnerable.

My question (at last :) ) Is this conclusion correct ? Did I forget an obvious solution ?

I cannot find any safer solution given the constraints (no expiry, use remember me feature)

Thank you for your help !

Community
  • 1
  • 1
Charly
  • 79
  • 9

2 Answers2

0

I'm not sure what your question is, but I'll use this space to clarify some stuff.

Your findings are correct: "remember the password" (even hashed) locally on device is a bad idea, should not be coded by anyone and users should never use an app that does it.

In reality even on the server side passwords should not be technically possible to be unencrypted. Server side password hashing must always use a 1 way encryption.

You never ever ever ever ever store password locally. Ever! You always store an oauth key locally. Hashed would be nicely. Even better if on the server side that Oauth key is tied to some sort of device ID, meaning that Oauth con only be used with that device.

What makes you think users have to "login again" when using Oauth? The keys don't have to expire (the server might have some expiration mechanism), and even if they do, there're key exchange techinques for that.

Budius
  • 39,391
  • 16
  • 102
  • 144
0

In principle you are correct, I will add just some technical notes.

https - for higher security use certificate pinning, your .apk should contain either certificates of allowed CAs, or signature of the server certificate, or public key to compare with server certificate (this prevents from man-in-the-middle SSL attack).

On server side store passwords as "strong_hash(salted(password))". Don't ever store plaintext password, or hashed-only. Whether salt is fixed, or generated per user (mangling user name into fixed salt), or per registration (you will be unable to login from different device, which doesn't know the proper salt), that's your choice.

About login (in case the "remember me" token expires): use always challenge-response way, so client will send his challenge to server, server will send his challenge to client, then client will send strong_hash(client_challenge+server_challenge+strong_hash(salted(password))), which server can generate from the stored strong_hash(salted(password)) too, and compare that (sending back "remember me" token, stored both on server/client side in encrypted form, with meta data about date of creation, etc.). If somebody is eavesdropping the communication, the hash sent will be valid only for those challenge values, next try to login on the same user account with different challenges would make it invalid.

If the security of the app data are really vital (like mobile banking), you can beef up the bad security of "remember me" to semi-secure level by encrypting the full "remember me" token by some simple "PIN", requiring the user to enter the PIN every time he runs the app. This makes it impossible to break in by hand (5-8 wrong PINs will delete the token and block the app, requiring full login with challenge+password, or even resetting the device by other channel (phone call, or web app) on the server), and brute-forcing it programmatically can trigger some alert on server API side of suspicious rate of failures for particular user. Yet entering 4+ digit PIN is not as cumbersome as entering full password, and it's usually well accepted by users in applications with high security requirements.

Otherwise yes, "remember me" can be stolen, it's just question how easy you make it, if the device has some tamper-proof keystore unlocked by the user presence, use that one instead of shared prefs, or at least encrypt the values with some key (fixed + generated-per-device part?). But it's just piling up stones on the path, somebody enough determined and skilled can extract the token anyway, and use it on other device to mimic the original user.

Ped7g
  • 16,236
  • 3
  • 26
  • 63