I am trying to understanding how the authentication of fb happens on mobile devices(ios/android)?
only for the first time when i installed the fb app, i entered the username/pwd. Thats it. from next time onwards, it will auto authenticate itself.
1) Does the fb mobile app stores the username/pwd on the device in any file?
2) will it use oauth or similar token mechanism? if so, where does the token stored on the device.
I guess, my question is, in which memory/path/filename it is stored, so that it is secured and cannot be accessed by other apps/root users.
Thanks much
That's a good question.
It's dangerous to store a user's password in a standard local directory on a device, for the obvious reason that if the phone is compromised a hacker may have access to a password that is likely shared between accounts (do you have a different password for every service you use?).
However, storing a username to the device's default storage is not-so-problematic, and that is generally the method of choice. For iOS this would be NSUserDefaults.
Now, in the case of passwords and tokens (which are certainly necessary and FB would not cut corners on having token-based auth), both being secure contents that ought to be protected, they are generally stored in some sort of encrypted keychain. In the case of iOS, 256-bit encryption by virtue of Keychain Services.
Therefore, when you build an application with auto-login you retrieve the password and token from the keychain on load. However, if the device were to be lost and end up in the wrong hands all of this data would be encrypted and inaccessible.
Of course, let's not pretend this method is fool-proof: http://arstechnica.com/security/2015/06/serious-os-x-and-ios-flaws-let-hackers-steal-keychain-1password-contents/.
EDIT: Although my background is iOS, I am aware that Android uses Keystore as their alternative.
https://developer.android.com/training/articles/keystore.html
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.
What is the best and safest way to save user credentials on device for an android app.
I was thinking of encrypting data and saving it in preferences.
Is there a way similar to iOS keychain to save passwords?
The best idea is not to save them at all. Encrypting provides very little security in this case because the app itself has to have the decryption key, so the key and data are on the same device. It will prevent only the least determined attackers. An OS level device isn't much better, as anyone with physical access can easily get around it.
The best idea is to use an access token. Get the login data once, send it to the server to login, and have them respond with an id. Use that id in future requests to identify yourself. The server should remember who is associated with each id. Preferably the server will include a timeout mechanism, where after X amount of time the id will be invalidated and the user will need to log in again. Even more secure implementations will match it to some physical id of the device as well, such as the Android device id, requiring attackers to have the device or fake both pieces of information.
The use of an access token rather than saving credentials protects the users in a few ways. First, the attacker will not know the users password in case its reused for other services (like their email). Second, it will not be enough to change their password (because a secure service will ask for the password again to change it) so while the info in the account may be compromised the user can take back the account by using their password to change their password. If the actual password is saved and lost the attacker can change the login info and lock the user out of his account permanently.
Adding the AWS access key and secret key directly in app code is definitely not a good approach, primarily because the app resides on the users device (unlike server side code), and can be reverse engineered to get the credentials, which can then be misused.
Though I find this information everywhere, but am unable to find a definitive solution to this problem. What are my options? I read about the token vending machine architecture for temporary credentials, but I am not convinced that it is any better. If I can reverse engineer the secret key, then I can reverse engineer the code which requests for temporary credentials. And once I have a set of temporary credentials to access S3, I am as good as if I had the key. I can request the temporary credentials again and again, even if they expire pretty quickly. To summarize, if an app can do something, I can do the same as a malicious user. If anything, the TVM can be a bit better at management (rotating credentials, and changing key in case of breach, etc.). Please note we can put the same access restrictions on the secret key, as we plan to do in case of TVM temporary credentials.
Additionally, if Amazon doesn't want people to use the secret key directly in the App, why don't they block it in their SDK, and enforce TVM or the correct solution. If you will leave a path, people are going to use it. I read several articles like these, and wonder why?: http://blog.rajbala.com/post/81038397871/amazon-is-downloading-apps-from-google-play-and
I am primarily from web background, so my understanding of this may be a bit flawed. Please help me understand if this is better, and whether there is a perfect (or may be good) solution available to this problem.
PS: Is there a rails implementation of TVM?
Embedding S3 keys in App code is very risky. Anyone can easily get that key from your app code (no reverse engineering or high skill set required), even if that is stored encrypted it is still compromised just that someone need to try harder (depending on how do you encrypt).
I hope that you understand the advantages of using temporary credentials to access Amazon (S3 etc) resources (mainly security + some others like no app update etc). I think you are more confused about the process to get the temporary credentials from TVM and how that is safer than embedding keys in code.
Every client using TVM first need to register with the TVM server implementation hosted by you. The communication between App (using TVM client) and TVM server is over SSL.
First the app register with TVM by providing UUID and a secret key. Please note that the secret key is not embedded in App code (which I think is main reason for your confusion) but generated randomly (using SecRandomCopyBytes which generates an array of cryptographically secure random bytes) at the time of registration (and hex encoded).
Once the device is registered successfully with TVM, the client TVM store the generated UDID and secret key in a storage called Keychain in iOS and Shared Preferences in Android. The keychain in iOS is the shared storage provided by iOS to securely (encrypted) store information (mainly keys, password etc).
After registration and UDID/Secret Key storage, App can get the token from TVM by sending the UDID, cryptographic signature, and a timestamp. The cryptographic signature is an HMAC hash generated from the timestamp using the secret key. The TVM can use the UDID to lookup the secret key and uses it to verify the signature. The TVM then responds by sending back temporary credentials, which are encrypted using the secret key (uses AES). The application decrypts the temporary credentials using the key and can then use them to access any AWS services for which the temporary credentials are authorized. Eventually, the expiration time of these temporary credentials will be reached, at which point the application can get the fresh temporary credentials, if required.
I am not sure how signed URLs relate to TVM, because I don't understand the concepts 100% but signed URLs really solved the problem for me. I needed a mechanism that would feed web app and mobile app data without allowing for misuse of the credentials. Putting the key in the code is indeed a very bad idea as it may generate a huge bill for the company.
After 3 days of extensive research, I found a simple and, what seems to be, a reliable and relatively safe solution: signed URLs. The idea is, that a very light-weight back-end can generate a temporary URL that will grant the user access to the specific resource for a limited time. So the idea is simple:
the user asks our back-end with a Rest call that he wants a specific resource
the back-end is already authorized with AWS S3
the back-end generates a temporary URL for the user and sends it in the Rest response
the user uses the URL to fetch the data directly from the AWS
A plug-and-play Python implementation can be found here and with a slight modification that I had to use: here.
Of course one more thing to figure out would be how do we authorize the user before we know that we can grant it the URL but that's another pair of shoes.
You should ideally use Cognito Identity for achieving this along with appropriate policies. It should be used with S3TransferUtility and S3TransferManager in iOS and Android SDKs. That would allow for background uploads and downloads as well. Cognito vends temporary credentials for access to AWS resources and is free. Also, you could federate it using UserPools or providers like Google, Facebook if you want secure access.
Thanks,
Rohan
If I want to store the username and password to be used inside an Android application, what is the best way to do it? Is it through the preferences screen (but what if the user misses this?), or pop up a dialog box and ask the user for the credentials? If so, I do have to maintain state for the application. How would I do this?
Most Android and iPhone apps I have seen use an initial screen or dialog box to ask for credentials. I think it is cumbersome for the user to have to re-enter their name/password often, so storing that info makes sense from a usability perspective.
The advice from the (Android dev guide) is:
In general, we recommend minimizing the frequency of asking for user
credentials -- to make phishing attacks more conspicuous, and less
likely to be successful. Instead use an authorization token and
refresh it.
Where possible, username and password should not be stored on the
device. Instead, perform initial authentication using the username and
password supplied by the user, and then use a short-lived,
service-specific authorization token.
Using the AccountManger is the best option for storing credentials. The SampleSyncAdapter provides an example of how to use it.
If this is not an option to you for some reason, you can fall back to persisting credentials using the Preferences mechanism. Other applications won't be able to access your preferences, so the user's information is not easily exposed.
You should use the Android AccountManager. It's purpose-built for this scenario. It's a little bit cumbersome but one of the things it does is invalidate the local credentials if the SIM card changes, so if somebody swipes your phone and throws a new SIM in it, your credentials won't be compromised.
This also gives the user a quick and easy way to access (and potentially delete) the stored credentials for any account they have on the device, all from one place.
SampleSyncAdapter (like #Miguel mentioned) is an example that makes use of stored account credentials.
I think the best way to secure your credential is to first think of storing the Password with encryption in the account.db file which couldn't be easily available in non rooted devices and in case of rooted device the hacker must need the key to decrypt it.
Other option is do all your authentication like the way Gmail is doing. after the first authentication with the Gmail server . you got the Auth Token that would be use in case of your password . that token would be store in plain text.this token could be false in case you change the password from Server.
the last option I'd recommend you to enable 2-Factor Authentication & create Device Specific Password for your device. After losing device, all you need is to disable that device.
Take a look at What is the most appropriate way to store user settings in Android application if you're concerned about storing passwords as clear text in SharedPreferences.
You can also look at the SampleSyncAdapter sample from the SDK. It may help you.
Take a look at this this post from android-developers, that might help increasing the security on the stored data in your Android app.
Using Cryptography to Store Credentials Safely
With the new (Android 6.0) fingerprint hardware and API you can do it as in this github sample application.
These are ranked in order of difficulty to break your hidden info.
Store in cleartext
Store encrypted using a symmetric key
Using the Android Keystore
Store encrypted using asymmetric keys
source: Where is the best place to store a password in your Android app
The Keystore itself is encrypted using the user’s own lockscreen pin/password, hence, when the device screen is locked the Keystore is unavailable. Keep this in mind if you have a background service that could need to access your application secrets.
source: Simple use the Android Keystore to store passwords and other sensitive information
The info at http://nelenkov.blogspot.com/2012/05/storing-application-secrets-in-androids.html is a fairly pragmatic, but "uses-hidden-android-apis" based approach. It's something to consider when you really can't get around storing credentials/passwords locally on the device.
I've also created a cleaned up gist of that idea at https://gist.github.com/kbsriram/5503519 which might be helpful.
I'm currently trying to build an authentication application in Android which stores users' username and password in the memory. Since sensitive information is stored, it would have to be encrypted.
And also the point is that the user does not need to enter a password, I would like to make it such that there is no master password for the app, assuming that the handset is secure.
As such, the encryption key would have to be stored somewhere. My question is, is there any mechanism in iOS/Android that protects my encryption key from being read by a malicious application with root access?
EDIT: I think it should be possible since web browsers store passwords, and I haven't heard a way to extract them.
NO, the user of your application has more control over the platform than you do. Or in this case if the phone was stolen, the new user has full control over the device. There is no place to hide a secret on any device. The same is true for desktop applications, mobile applications and web browsers.