0

I've been searching for a clean, reliable way to persist the current user in an Android app, which is accessible from any activity/view, is available immediately, and can be reliably cleared upon logout.

To add further context, the app handles API authentication via a token (JWT). Unfortunately there is no user info in the payload.

There is an MVVM architecture, and there is a Repository layer, which calls a retrofit api/room db.

Here are the things I'm exploring, would love to know if any are any better ways to go, or if there's another pattern/architecture I've not discovered yet:

  • Presently a User object is persisted on the Application class. I hate this personally, it's what existed previously. Upon successful login, the JWT is stored in SharedPreferences, and the User object is saved as a static variable in the Application class.
  • Immediately there is the thought to at least store the important bits of the user in SharedPreferences too. I was trying to find someway to "bundle" the user with the JWT, sharedpreferences doesn't really play nicely with objects though. I imagine a scenario where I may have a stored token for one user, but the User object for another, which will cause all sorts of problems.
  • As well as our retrofit API service layer, there is a basic Room db spun up as I slowly try to incorporate local caching throughout the app. So I know I can persist the User here, although worried about the async nature of DB calls.
  • I feel what I'm after is some kind of architectural layer, a SesssionManager or something, that takes care of all of this. Will "hold" the User, the Token, have a global Logout() method, will somehow play nicely with the repository layer, so the View and ViewModels don't really need to bother with the user or userId at all, just make the various repository calls, and the data (repository/retrofit service) layers will return what is right for the currently logged in user etc.

Sorry if this is a bit abstract/high level without any specific code, I just remember finding months ago an excellent article to do with this notion of a Session layer, and didn't bookmark it and now am scratching my head trying to work out the best way to achieve this cleanly.

Vin Norman
  • 2,749
  • 1
  • 22
  • 33
  • `I just remember finding months ago an excellent article to do with this notion of a Session layer, and didn't bookmark it` -> checked your browser history? – Marcin Orlowski Jun 05 '19 at 14:04
  • Haha yes, needle in haystack with the amount of articles I read every single day, and only goes back to about March for some reason, may have disappeared into chrome vacuum somehow – Vin Norman Jun 05 '19 at 14:05
  • Well as long as you guys survive [this scenario](https://stackoverflow.com/questions/49046773/singleton-object-becomes-null-after-app-is-resumed/49107399#49107399) deep in the app.. – EpicPandaForce Jun 05 '19 at 14:16
  • That's the main reason I hate the static variable in Application class thing. And singletons really, short of dependency injection. I just wanted to know if there was any patterns for checking the current user, which avoids singletons. – Vin Norman Jun 05 '19 at 14:22
  • If you don't like static variables, you can extend Application class, add your own member variable to it (not static) with corresponding getter/settter and then use `getApplication().getMyUser()` construct. Upon logging in, you would call `getApplication().setMyUser(user)` and set it to `null` on logout (or add another method `clearMyUser`) – Aleks G Jun 05 '19 at 15:42
  • Using Shared Preferences to store JWT token is ok as long as you use encryption, e.g. Keystore with AES etc. Then you have to create a user account util where you can grab the token from shared preference and restore the UserAccount with the token and other user information. Again the util might reside on a singleton preferably within dependency injection. Or you can try -> https://developer.android.com/reference/android/accounts/AccountManager – Rodrigo Queiroz Jun 05 '19 at 16:23
  • Keep it database, sharedpreferences are pain in neck when it comes to migration. Avoid sharedpreferences at all cost. Store it once, inject/pass it where you need it. – Nikola Despotoski Jun 05 '19 at 23:37

0 Answers0