I'm developing an app which will connect to server webservice and exchange data. I want to include auto authentication mechanism in application. I'm not really good at security stuff, so I would like to ask you, how to do it properly. I think, that storing users password in sharedpreferences or database and comparing it with password stored in server is not a good idea, even in encrypted form. I guess that there is some better way to do it, right?
Normally the service will return a key of some sort (typically in a cookie), and you pass that key with each subsequent request. The server is responsible for keeping track of who has what key. And of course the key is very large so its unguessable.
On the server side, never store the password. You store a hash of the password, and when an incoming password comes from a login request, you hash it and compare the hashes. Better yet you should salt your hashes as well. If you aren't familiar with security I'd really suggest you use an existing library rather than writing your own.
Related
I need to store user credentials in my Android app. The application sends HTTP requests to a server and the credentials are used to authenticate with that server.
I know that many articles and many discussions about this topic already exist. However, I would like to ask for help considering the following specific requirements:
The user should be asked to type username and password just once. After that, the application must be able to authenticate with the server forever.
If the server receives an authentication request that contains username and password, it generates a random token and sends it back to the client.
The client must add the token to other requests (as an HTTP header).
The validity of the token always expires an hour after it was generated. The client must send another authentication request with username and password to get a new token.
Note that the server provides a custom authentication mechanism that does not follow any standard.
I would say that these are very strong requirements and that they already impact some security issues. However, let's suppose that these conditions cannot be changed and that they must be met by the Android app.
Here is what I am going to do:
As the user should provide credentials just once per app installation and as the token on the server side has a limited validity and the client must re-authenticate with the credentials again and again, the Android app cannot avoid storing the password.
I will store the credentials into DB (by subclassing SQLiteOpenHelper from the android.database.sqlite package).
I will encrypt the credentials before storing them but the key used for encryption/decryption will be just a constant hardcoded in the app.
Additionally I will set android:allowBackup to false in the manifest file and obfuscate the application.
I know that an attacker with physical access to the device can get the credentials. I am also aware that some of the suggested steps are just little obstacles for such attacker.
However, is there something more I can do to improve security if there are the requirements mentioned at the beginning of the question?
Thanks.
If I were in your shoes, I would use SQLCipher to store the user credentials. This is a simple way to create and use an encrypted (using AES) sqlite database with minimal hassle.
Of course, this doesn't solve the whole problem. You still need a secure way of generating/storing the key to said database. If I were to recommend any option, I would advise requiring users to input a password/PIN whenever they open the app, and use said password/PIN as the database key.
An alternate method would be to generate a unique, random key upon app installation, and store it in the Android Keystore. A truly dedicated/well-funded attacker would still be able to retrieve the key, but only for the database on that one device.
I've been mostly creating smaller apps and games for Android so far, but am now creating a somewhat big app with lots of users and more sensible data than a highscore.
My normal approach was to just have a table for all users with passwords, authenticate with a simple Login Screen using a HTTP(S) call and that's it.
There's a few things I want to improve for this app though:
Secure Transmission
If I want to encrypt the user's password, where do I need to do it? On the device, before it's even sent? (In case of unsecure networks, like a public WiFi hotspot) Or better on the server, before writing it into the DB? Or should I just use SQL's encryption?
Auto Login
I want users to be able to stay logged in until the log out - how would I best do that? Not just security-wise, but also for the user experience.
My research shows me that using the AccountManager would be best to save the username and password and authenticate automatically when the app is started. Is there anything more to it, any security risks I'm missing here?
Access control
Usually, I would just expect every call made by an app to be valid, since a user can't access anything but the login screen without logging in. But how do I best authenticate a user's request to make sure that it's not an attacker? I can't just send the username/id with every request, so I probably need like a session token that I generate on each login? Or is there a better method?
Is there anything else I've forgot to think about?
I would suggest you to transfer password without encrypting it but by https. Other way would be to implement asymmetric encryption in your app and encrypt password with public key which you will receive from server.
On the server side I would hash password using some hashing algorithm with salt. And store only hash and salt. When users will log in, you can hash incoming passwords the same way and check hashes on equality.
To make auto login, you need to sign all requests from authorized users with a token. Token you will receive from the server after successful login. This token could be stored in Keystore, or special storage which is accessible only for this application.
Signing could be implemented by attaching to request additional parameter with checksum from all request parameters and token.
Additionally I would suggest you to think about unauthorized clone apps, which could pretend to be your app and call your server side API.
My mobile app has users, so after someone log in, I send back the user id to be used for future requests (GET and POST HTTP web service calls to manage user data), and I store it in an sqlite table called user_settings after encrypting it using jbcrypt along with the salt. is this a safe way to do it?
You could use sqlcipher to encrypt the database with a randomly-generated key, created on first startup, that you store in the Android Keystore System.
As #njzk2 said, there is no way to absolutely protect this data. Encrypting the database with a random, unique key, and stashing that key in the keystore, will make things much more difficult for an attacker, even with physical access to the device. In this scenario, the goal is not to keep the attacker from ever accessing the password, but slowing the attacker down enough that the user can change their password before the attacker can use it.
I am making a trivia android application, and I have the questions and answers database stored on my server. In my app, the user types in his/her username and password, and this is sent to a servlet, which then authenticates it with the Database. If the authentication was successful, the user information for the particular user will be downloaded and stored in SharedPreferences. In the user information, there is a user key that is used to access the server again to update user information, and get other values from the database such as the questions and answers. However, this is not very secure as any attacker can create an account, login, and find the user key and use it to get the trivia answers. Should I use a keystore or a token system in my server to authenticate a request for the database. How should I do this? Thanks for the help!
You could scramble the key before putting it in shared pref, and then unscramble it before sending it to your server each time... not to say someone couldn't reverse engineer your app to look at your algorithm and figure out the real key. But then again, how hard are people really going to try to cheat at trivia?
The most secure way would be not to send the answers. Send the user's answer to the server, and have the server check the answer and return right or wrong.
Use PGP encryption. Encrypt user/pw using public key in android then decrypt it using private key in the server. mcrypt or openssl can do that for you.
In developing an Android application that will store certain user date into a sqlite database, how should I handle a user password securely? How can I encrypt the password so that it does not appear "in the clear" in the database, but so I can decrypt it in the application when needed.
Storing user credentials in a database presents many security challenges. You may want to consider an alternative (e.g. using OAuth 2.0 Authentication). We don't need yet another Android app with security vulnerabilities. Here is a ref for OAuth 2.0 Authentication from Google.
While one alternative that many folks do use is to "hash" the username and password using an algorithm like SHA-1 (MD5 has some vulnerabilities, though it is also used often)
The best approach would be to store SHA-2 (or some other type of hash) of the password, and then compare those hashes instead of the actual decrypted passwords.
Storing passwords is a bad practice and is not secure even if they are encrypted. Remember, everything can be broken. The best you could do is to make things more difficult for the hacker.