I am going to use oAuth to fetch mails and contacts from google. I don't want to ask the user each time to log in to obtain an access token and secret. From what I understood, I need to store them with my application either in a database or SharedPreferences
. But I am a bit worried about security aspects with that. I read that you can encrypt and decrypt the tokens but it is easy for an attacker to just decompile your apk and classes and get the encryption key.
What's the best method to securely store these tokens in Android?
-
2How do i store the consumer key and secret (hardconding them is not secured)? i need them to request the accesstoken and secret.. how do the other existing apps using oauth do it? hmm finally with oauth, you need to take care of much more security issues for me.... i need to keep the consumer token/secret securely and also the accesstoken and secret.... finally wouldn't it be more simple to just store the user's username/password encrypted?... in the end, isn't the latter better? I just still can't see how oauth is better... – yeahman Apr 15 '12 at 15:45
-
can you tell me..which file stores the access token ?? I am new to android and i tried running sample Plus app.But i dont find this anywhere [GoogleAuthUtil.getToken() method.] – Abhishek Kaushik Jun 03 '14 at 11:09
5 Answers
Store them as shared preferences. Those are by default private, and other apps cannot access them. On a rooted devices, if the user explicitly allows access to some app that is trying to read them, the app might be able to use them, but you cannot protect against that. As for encryption, you have to either require the user to enter the decrypt passphrase every time (thus defeating the purpose of caching credentials), or save the key to a file, and you get the same problem.
There are a few benefits of storing tokens instead of the actual username password:
- Third party apps don't need to know the password and the user can be sure that they only send it to the original site (Facebook, Twitter, Gmail, etc.)
- Even if someone steals a token, they don't get to see the password (which the user might be using on other sites too)
- Tokens generally have a lifetime and expire after a certain time
- Tokens can be revoked if you suspect they have been compromised

- 26,736
- 15
- 188
- 224

- 52,576
- 10
- 84
- 84
-
1thx for the reply! but how can i know if my consumer key has been compromised? lol it's will be hard to tell.. ok about storing the access token and secret, ok i save them in sharedpreferences and encrypting them but how about consumer key and secret? I can't store them in sharedpreferences (I would need to explicitly write the consumer key and secret in the code to save it in sharedpreference in the first place).. don't know if you understand what i mean. – yeahman Apr 15 '12 at 16:14
-
2You have to either put the in the app in a (somewhat) obfuscated way, to they are not immediately visible after decompilation, or use your own authrorization proxy webapp that has the key and secret. Putting them in the app is obviously easier, and if think the risk of someone trying to crack your app is sufficiently low, take that approach. BTW, the points above are for the user password. If you find out your consumer key/secret have been compromised, you can revoke those too (that will, of course, break your app though). – Nikolay Elenkov Apr 16 '12 at 05:35
-
ok thx .. i will go with the obfuscation way (can you recommend any good tool to do it?) ... having a proxy webapp is not very appealing as i would have to force my users to register to my site.. not very user-friendly adding an additional step in the whole chain... – yeahman Apr 16 '12 at 16:17
-
1@NikolayElenkov: You wrote 'As for encryption, you have to either require the user to enter the decrypt passphrase every time (thus defeating the purpose of caching credentials), or save the key to a file, and you get the same problem.'. What if crackers reverse your app to get insight how the encryption works? Your defense may be broken. Is it a best practice to store such information (token, encryption...) using native code? – anhldbk Nov 12 '14 at 10:03
-
1If app data is cleared, then the refresh token is lost, which is probably not what the user wanted. – rds Oct 21 '15 at 20:44
-
You can use tokens that need signature verification at the Backend too (like JWT) link : https://jwt.io/ . Thus restricting attackers to create fake tokens. – shikhar bansal Jan 10 '17 at 21:08
-
1
-
9
-
3
You can store them in AccountManager. It's considered best practice according to these guys.
Here's the official definition:
This class provides access to a centralized registry of the user's online accounts. The user enters credentials (username and password) once per account, granting applications access to online resources with "one-click" approval.
For detailed guide on how to use AccountManager:
However, in the end AccountManager only stores your token as a plain text. So, I would suggest encrypting your secret before storing them in AccountManager. You can utilize various Encryption library like AESCrypt or AESCrypto
Another option is to use Conceal library. It's safe enough for Facebook and much easier to use than AccountManager. Here's a code snippet to save a secret file using Conceal.
byte[] cipherText = crypto.encrypt(plainText);
byte[] plainText = crypto.decrypt(cipherText);

- 17,295
- 5
- 53
- 64
SharedPreferences is not a secure location itself. On a rooted device we easily can read and modify all applications' SharedPrefereces xml's. So tokens should expire relatively frequent. But even if a token expires every hour, newer tokens can still be stolen from SharedPreferences. Android KeyStore should be used for long term storage and retrieval of cryptographic keys which will be used to encrypt our tokens in order to store them in e.g. SharedPreferences or a database. The keys are not stored within an application's process, so they are harder to be compromised.
So more relevant than a place is how they can be itself secure e.g. using cryptographically signed short-living JWTs, encrypting them using Android KeyStore and sending them with a secure protocol

- 603
- 1
- 6
- 20
-
14
-
2@MilindMevada by using [android account manager](https://developer.android.com/training/id-auth/identify) (with manual encryption, since account manager only store a plain text), or an [android keystore](https://developer.android.com/training/articles/keystore) – Ezra Lazuardy Aug 15 '20 at 09:30
-
1Security is hard. Everyone is always jibbering and jabbering and in the end every solution is never really secure. Because it's like a door; it needs to be opened in order to expose what's inside and closed to conceal what's inside. The trick is how do you know the person opening the door is allowed and authorized to open it? – TheRealChx101 Oct 25 '22 at 08:22
Just as a late update to this question, you can now use EncryptedSharedPreferences to store data securely. The interface is very similar except that you also need to generate a MasterKey.
Most of the docs for EncryptedSharedPreferences use MasterKeys.getOrCreate(MasterKeys.AES256_GCM_SPEC, but that appears to be deprecated in favor of MasterKey.Builder.
private var masterKeyAlias = MasterKey.Builder(context, MasterKey.DEFAULT_MASTER_KEY_ALIAS)
.setKeyScheme(MasterKey.KeyScheme.AES256_GCM)
.build()
private val preferences = EncryptedSharedPreferences.create(
context,
"auth_token_secured",
masterKeyAlias,
EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
)
var authToken: String?
get() = preferences.getString("auth_token", "")
set(value) = preferences.edit().putString("auth_token", value).apply()

- 61
- 1
- 3
-
1Don't forget to add the import to build.gradle implementation 'androidx.security:security-crypto:1.0.0' – htafoya Dec 09 '22 at 10:27
Auth0 provides a utility class to store tokens. Its better to use that utility library. There are two classes you can use to manage credentials:
- CredentialsManager stores data in plain text
- SecureCredentialsManager encrypts the data before storing it, using
a combination of RSA and AES algorithms along with Android
KeyStore.
Link to documentation: Auth0.Android Save and Renew Tokens

- 3,880
- 2
- 25
- 32