4

I started to learn Android few days back and so far I am done with implementing Login Activity, Main Activity which extends abstract Base Activity.

Nav Bar item when clicked opens xml from Fragments.

I have a question about the token that I receive after successful login. This token is being used with each request to get data after successful login. Should I save the token in sqlite database securely or I should make a public property in Main Activity? Main Activity will always remain in memory as this will open fragments.

Sergio
  • 27,326
  • 8
  • 128
  • 149
Pankaj
  • 9,749
  • 32
  • 139
  • 283
  • you can use `sqlite database` – IntelliJ Amiya Mar 21 '17 at 09:29
  • 3
    It fully depends on your App design. Will you ask for Login when the App is restarted? Will you save the session? How secure do you want it to be? SQLite can be extracted and read if a phone is rooted. – JonZarate Mar 21 '17 at 09:32
  • 1
    Be super careful when implementing solutions provided below. Most of what I read are not secure. Good luck. – JonZarate Mar 21 '17 at 11:21
  • @JonZarate: Bounty is added. Kindly suggest your opinion. – Pankaj Apr 07 '17 at 20:43
  • 1
    Think about what happens if the token gets _leaked_. Is it usable on another device? Is it valid _forever_? Can the user logout and invalidate it? Is the information an attacker could obtain sensitive? It really all depends on how secure you want your app to be. – David Medenjak Apr 09 '17 at 15:59
  • @JonZarate What do you think is the best way to store securely things locally? – Antonios Tsimourtos Apr 13 '17 at 15:31
  • 1
    Storing in sqlite is not a good idea. If not set properly in the manifest the database can be exported. Easier still if the device is rooted. – Juan Apr 14 '17 at 14:45

7 Answers7

4

I can suggest 3 options: 1) you can save the token to the file, something like this:

public static void saveToken(Context ctx, String fileName, Object token) {
        if (token == null) {
            ctx.deleteFile(fileName);
        } else {
            ObjectOutputStream out = null;
            try {
                FileOutputStream fout = ctx.openFileOutput(fileName, 0);
                out = new ObjectOutputStream(fout);
                out.writeObject(token);
                fout.getFD().sync();
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                try {
                    if (out != null)
                        out.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }

Make sure object token implements java.io.Serializable interface.

Usage before API level 24:

saveToken(appContext, someFileName, someTokenObject);

Usage with API level 24 and higher:

saveToken(appContext.createDeviceProtectedStorageContext(), someFileName, someTokenObject);

2) Use SQLCipher library for encrypted database.

3) You can encrypt your token using keystore system https://developer.android.com/training/articles/keystore.html

Sergio
  • 27,326
  • 8
  • 128
  • 149
2

Use SharedPreferences and make sure you are using Context.MODE_PRIVATE this way only your app can access the data. SharedPreferences is a persistent store

e.g.

SharedPreferences prefs = context.getPreferences(Context.MODE_PRIVATE);
prefs.edit().putString("token", token).apply();
token = prefs.getString("token");

Why not to use SQLite:

SQLite is a database and is targeted at tabular data, a single token does not fit this use case.

Why not store in the main activity:

The main activity will not be around for the lifetime of the application install, it can be cleaned up by the OS at any time. It is not a persistent data store.

Ryan
  • 1,863
  • 13
  • 20
0

Should I save the token in sqlite database securely or I should make a public property in Main Activity? Main Activity will always remain in memory as this will open fragments.

The Official Android documentation already answers your question in the section on called "Best practices for security and privacy". It gives the following statement:

If you have access to user data and can avoid storing or transmitting it, don't store or transmit the data

In other words, if you can avoid persisting then don't persist it.

You mentioned "public property" in your question which makes me wonder if the concept of visibility modifiers is not yet clear. The Java public and private modifiers are for controlling access to the members of your class. They have nothing to do with security as per this answer here.

If you do persist the token in memory, as a public field or otherwise, you may reduce your exposure slightly by storing the token in a char[] rather than a String. That also is detailed in this canonical answer.

Finally, if you do have to store the token, the sqlite database is not the correct place to do it. Instead, you should use the provided KeyStore which will make for more difficult extraction of the token in the case that the device is compromised. The link to the documentation above is complete with code examples. If this proves too difficult to use, there are some wrappers around it including Scytale.

Community
  • 1
  • 1
David Rawson
  • 20,912
  • 7
  • 88
  • 124
0

1) Store the token value within the base application singleton (where your application must be an instance of BaseApplication)

public class BaseApplication extends Application {
    // token
    private String token = null;
    public String getToken() {return this.token;}
    public void setToken(String token) {this.token = token;}
}

With the implementation above you will be able to set and get the token value from any activity/fragment. However the value is not persistent and it will be lost once the application ends.

Remark: If you are using the token for REST api access then you can store the token in the background service instance using a similar solution as above.

2) Use SharedPreferences - this is recommended way in case you want to store the token's value between application's runs.

Please see the answer from @Ryan.

toro
  • 19
  • 5
0

You can use SharedPreferences to store token.it is available over application.

Chetan Chaudhari
  • 323
  • 5
  • 15
-1

Better to use Sqlite or Realm. And store in Application memory and not in external memory. As for data residing in application memory we don't need to worry much about security. Saving in MainActivity is not a good solution, as once application closes, this will get cleared.

Storing in Shared Preference is also an option. But if user clears the cache from setting's this value will also get cleared. Realm Android Reference Link

Sreehari
  • 5,621
  • 2
  • 25
  • 59
-1

You can store it in Shared Preference as this one is token.

Now coming to the part of Security You can obviously use encryption for the shared preference.

There are already lots of open items available you can use below library for example https://github.com/ophio/secure-preferences Regarding keys that are in your java file to encrypt, You need to be sure you are applying proguard before you upload it to playstore.

In that manner now your token is fully secure with shared preferences.

In order to save it in sqlite than by decoding or root access your db file can also be accessed same as preferences. Regarding clear data from setting I think it will delete your sqlite data as well. Not sure about this though.

I hope it will help you out.

Mushahid Khatri
  • 728
  • 4
  • 12
  • 1
    `You need to be sure you are applying proguard before you upload it to playstore` obscuring code doesn't mean it's safe. Not to mention ProGuard doesn't obfuscate Strings IIRC. – JonZarate Mar 21 '17 at 10:15
  • Can you take value for perticular String from Proguard applied code? Can you find in which class it is? – Mushahid Khatri Mar 21 '17 at 10:31
  • http://stackoverflow.com/questions/10220069/does-proguard-work-to-obfuscate-static-string-constants – JonZarate Mar 21 '17 at 10:32
  • @JonZarate , convert String into char array – Vyacheslav Mar 21 '17 at 10:33
  • 1
    @JonZarate , it is possible to find but it is better idea. – Vyacheslav Mar 21 '17 at 10:33
  • @JonZarate, Yes its correct that it will not change string. You you will not be able to find where this string is, also why to declare it as static, Just declare private key in your shared preferences class(Secured Preference class) – Mushahid Khatri Mar 21 '17 at 10:38
  • @JonZarate And I think this is the only best option to store token rather than storing it in sqlite. – Mushahid Khatri Mar 21 '17 at 10:39
  • @MushahidKhatri It's the same to store it in SQLite and SharedPreferences in a rooted phone. Both equally vulnerable. The database has no protection and the SharedPreferences is a human readable XML. – JonZarate Mar 21 '17 at 10:42
  • @JonZarate That is what I wrote in my answer "In order to save it in sqlite than by decoding or root access your db file can also be accessed same as preferences." But to store in sqlite due to only one value you need to create db, You need to call db every time you need to fetch token. So better to use preferences as you will be using for other values as well. And encryption to preference will some how help to fetch data from xml to other, even device is rooted :) – Mushahid Khatri Mar 21 '17 at 10:45
  • @MushahidKhatri You are not paying attention to my messages. My first comment stated that your encryption key will not be secure. You can encrypt your key in DB or SharedPreferences, doesn't matter, if the key is hard-coded in your program. – JonZarate Mar 21 '17 at 10:47
  • @JonZarate, It will be hard to find key if it is not static and proguard is applied. Also I found that you are just telling its not proper, But some one has also asked you do you have solution than this? I am also asking you do you have solution than this? You just gone silent. – Mushahid Khatri Mar 21 '17 at 10:51
  • 1
    @MushahidKhatri `It will be hard to find key if it is not static and proguard is applied` False. You just say things you do not know about all the time. `You just gone silent ` Why does it matter to you if I know a solution? Doesn't change the fact that your approach is vulnerable. Anyway, yes, I solved it, but it's useless to explain it to you, since you don't pay attention to what I say. – JonZarate Mar 21 '17 at 10:57
  • Don't give argument if you don't have any better solution. – Paresh P. Mar 21 '17 at 10:57
  • @JonZarate If you have solved it than you would Probably have answered before me. You didn't Proves all. – Mushahid Khatri Mar 21 '17 at 10:59
  • Dude that is what is stackoverflow is about! Sharing knowledge, fix problems! – Paresh P. Mar 21 '17 at 11:00
  • @MushahidKhatri hahaha, no. I don't care about reputation, but if I see a bad answer I will say it. Keep Googling. – JonZarate Mar 21 '17 at 11:01
  • @JonZarate 'The fact that I am not sharing it, doesn't mean I don't have it. **Go search on Google like I did**' Who is googling? – Mushahid Khatri Mar 21 '17 at 11:04