1

In my application, I store sensitive user data (like bank details) and the user can lock each of the details by using a separate password. I want the user to set a master password as soon as he runs the application for the first time after installation, so that he may recover data by entering this master password in case he forgets a password.

So, when the application is run for the first time after installation, there would be a pop-up asking him to set the master password and the user needs to set the password to continue further.

But, when the application would be started after a phone restart or maybe after closing the application, he should not get the pop-up.

The pop-up should come once and only once when the application is run for the first time after installation.

Assuming setMasterPassword() is the function which creates the dialog, where do I call this function on first run ?

Does android have any parameters to determine that the app has been newly installed ?

Or should I just use Preference Variables to check this ? {Something like initializing the counter in the PreferenceVariable as 0 and then checking this value in onCreate() and calling setMasterPassword() if and only if the counter is 0 and then incrementing the counter by 1 so that it would never be called again.}

What would be the best way to do this ?

Thanks in advance!

Swayam
  • 16,294
  • 14
  • 64
  • 102
  • possible duplicate of [Determine if android app is the first time used](http://stackoverflow.com/questions/4636141/determine-if-android-app-is-the-first-time-used) – Jannie Theunissen Jun 11 '15 at 07:32

4 Answers4

2

I have also tried to figure out if there is a "fresh install" boolean, but it seems there is nothing like that, so you should go for a shared preference, like the folk did here.

PS: By the way, it's a duplicate of that question.

PS2: Keep in mind, if the user deletes all the stored information of your application, the check will also be erased and thus you'll be able to enter this again.

How to improve your information security:

  1. Store the user's information along with some control bytes (a random number, a specific string, whatever) and encrypt this with the user's password.
  2. Anytime you need the user's information, grab that file, try to decrypt its content with the user's password (asked each time)
  3. Check for the control bytes (a substr() will suffice, probably). If they're the same, then grab the information. If they're not, prompt again.

This way, you get some benefits:

  • You don't store the user's password anywhere. SharedPreferences won't store this, just the "firstTime" variable.
  • If the user dumps the application's information, putting again a password won't reduce your information.
  • Opening that file from an explorer will only show a bunch of numbers, symbols and probably non-readable bytes that will mostly break the editor.
Community
  • 1
  • 1
Sergi Juanola
  • 6,531
  • 8
  • 56
  • 93
  • Yeah so if my phone falls on other's hand and he deletes all the app info from the phone, then the master password will be asked again. And the other user can set a new password and easily access all the data even if he doesn't know the password to each file. Security becomes pointless in that case. – Swayam Aug 08 '12 at 18:10
  • Hence my reluctance to implement it in the PreferenceVaraibles. Is there no other method possible ? – Swayam Aug 08 '12 at 18:12
  • 1
    Have you thought about encrypting the information you store? Actually, if the only protection is to open a file or not, you can get that file with any file explorer. Check my edit – Sergi Juanola Aug 08 '12 at 18:20
  • Thanks for the suggestions. Yes, the data would be encrypted and saved. But my concern is that if a malicious user sets a new masterPassword, then the application would happily decrypt things for him even if he doesn't the password to the respective files. The masterPassword is there to help the user retrieve info even he forgets the password he has set to a file. So, even if another user clears the application info and creates a new masterPassword, there would be no way to detect this. – Swayam Aug 08 '12 at 18:25
  • @swayam IMO better, for such sensitive information, to have service based app initialization. If user went through initialization flag will be set on the server side. If somebody remove the app without removing that flag, initialization flag will stay. Second initialization will check deviceID and fail to set new password. THis is what I'm doing. – Maxim Aug 08 '12 at 18:27
  • Oh, I have thought about this too! But the drawback that I felt this has is asking for Internet connection everytime the app is opened. What if there is no internet connection ? Do you think that users would like to depend totally on the internet ? What if he is out of network and wants to access details ? What if the web-service is taking too long to respond ? There are so many problems that could come up if I made the app totally dependent on internet connection. I am not a huge fan of no-internet-no-access. :) – Swayam Aug 08 '12 at 18:33
  • Ah dang, sorry, I totally skipped the "master password" thing. In that case, I would also go for a webservice, like @Maxim suggested. – Sergi Juanola Aug 08 '12 at 18:37
  • @swayam In my view you need internet to initialize password set up. And let service know that password is initialized. If user want's to reset password then connection should be available. You will use password + some algorithm to protect data. You won't store pass. Every time user provide pass, u use it to extract data and show. No connection necessary. – Maxim Aug 08 '12 at 18:45
  • @Maxim : Yes, I get your point that there would be no connection necessary to decrypt data but every time the app is run wont a request be sent to the server to check if the application already has a password attached to it ? – Swayam Aug 08 '12 at 18:56
  • @swayam if somebody doesn't know password they won't be able to decrypt data. If they remove your app, data will stay encrypted. If they try to initialize app again you'll find out that this particular device had password setup. You can run then question-answers round to allow to generate new password. If they try to change pass service will ask an old password first. Server doesn't need to know if password still attached, anyway if password unknown data stay encrypted. – Maxim Aug 08 '12 at 19:08
  • @swayam Ohh I see what you mean. Ask password or don't ask first run. Here you can use preferences. Just to tell to the app to show or not password setup screen. – Maxim Aug 08 '12 at 19:11
2

Found this code somewhere and it is working for me perfectly. So, I thought it might help you too.

Have a look.

Use SharedPreference to store the firstrun value, and check in your launching activity against that value. If the value is set, then no need to display the dialog. If else, display the dialog and save the firstrun flag in SharedPreference.

In your MainActivity:

public void onCreate(){
    boolean firstrun = getSharedPreference("PREFERENCE", MODE_PRIVATE).getBoolean("firstrun", true);
    if (firstrun){
   [[ ...Display the dialog ]]
    // Save the state
    getSharedPreference("PREFERENCE", MODE_PRIVATE)
        .edit()
        .putBoolean("firstrun", false)
        .commit();
    }
}
1

And thus the disadvantage of single pass authentication. If a malicious user manages to get/change the password no mechanism you put in place will stop them. If the information really is that sensitive you may want to enable a second authentication mechanism (security question, email confirmation, etc.)

D.A
  • 2,555
  • 1
  • 14
  • 10
  • Or I could clear my phone database whenever a new masterPassword is set ? That would delete all the files and the malicious user would get no data to access. – Swayam Aug 08 '12 at 18:42
  • 1
    That would work too. But if the user changes their password regularly (like we were all taught to do) it could get annoying for the user. As the developer you are going to have to strike a balance between security and usability. I would recommend not using the password as a key (people are notorious for creating bad passwords) and use your own key. Then require some kind of second authentication (email confirmation after the password was entered maybe? Of course if the email goes to the phone that could be useless.) to access the data. – D.A Aug 08 '12 at 18:47
  • 1
    maybe he can take advantatge of shared preferences in this case. If the user is prompted for a fresh install, then delete anything. If he tries to reset password (which differs from a fresh install), he can keep the information. It's all about designing a good user interaction. – Sergi Juanola Aug 08 '12 at 18:48
  • That could work. It really comes down to how he's storing all this data too. I think he has to understand his big picture before any technical talk starts. – D.A Aug 08 '12 at 18:53
  • Thanks for the suggestions. I guess I could check for a fresh install or changing of password and take action accordingly. But then again, everything gets dependent on the SharedPreferences. I guess that would be the only offline way to do it, the other being sending an authentication request to a server. – Swayam Aug 08 '12 at 19:03
0

The best way is to probably set a receiver upon install.

<receiver android:name =".CLASSNAME">
     <intent-filter>
                 <action android:name="com.android.vending.INSTALL_REFERRER"/>

      </intent-filter>
      </receiver> 

(You will need to create a BroadcastReciever extended class called "CLASSNAME" for it to pick up the broadcast, in case you were not familiar with these.)

Also, install referrer will not work unless its out on the market, so you may follow this stack overflow answer in simulating a fake install; How to test android referral tracking?

Best of luck.

Community
  • 1
  • 1
programmer33
  • 642
  • 8
  • 19
  • 2
    Note that the newly installed package does not receive this broadcast. So he will need another app previously installed, just to controll that event? – Maxim Aug 08 '12 at 18:14
  • @Maxim : I am familiar BroadcastReceivers but not with the PACKAGE_ADDED action. Are you sure that the newly added package would not receive this broadcast ? – Swayam Aug 08 '12 at 18:18
  • I copied "Note" from the reference. http://developer.android.com/reference/android/content/Intent.html#ACTION_PACKAGE_ADDED – Maxim Aug 08 '12 at 18:20
  • Sorry I gave the wrong name try this receiver; "com.android.vending.INSTALL_REFERRER" ... you can also leave out scheme in your receiver manifest declaration – programmer33 Aug 08 '12 at 18:21
  • I am sorry but I didn't understand what you meant by leaving out "scheme" in my manifest ? – Swayam Aug 08 '12 at 18:37
  • It was a flag that was associated with package added. For your convenience, I have fixed it in the above code. – programmer33 Aug 08 '12 at 18:42