Marky
Marky

Reputation: 1304

Sharing oauth token between my apps on Android - Shared User ID, Keychain, AccountManager or something else?

I'm trying to work out the best solution for a particular situation I'm in, and am having trouble working out the best option. It's a tricky setup, so might be a fun challenge for you Android experts! Here's my situation:

I hope that all makes sense!!! Please let me know if not.

I'm now trying to work out the best method for storing oAuth tokens (plus some additional data such as email address to go with it) on Android so that other apps owned by our account can access them in order to exchange for a fresh token.

I've looked into using the following, but am unsure of the best route:

  1. SharedPreferences along with sharedUserId
  2. AccountManager (https://developer.android.com/reference/android/accounts/AccountManager.html)
  3. Android Keychain (https://developer.android.com/reference/android/security/KeyChain.html)
  4. ContentProviders

The problem with option 1. seems to be that setting the sharedUserId after first release will lose access to all of the data (see http://java-hamster.blogspot.jp/2010/05/androids-shareduserid.html). This is not a nice thing for our users.

Option 2. (AccountManager) could be a good option, but if we want to store the tokens separately (per-app), but want any other apps we make to access their tokens, I'm not sure how we'd do that.

Option 3... is it possible to do what we need with Keychain?

If I understand correctly, option 4 would need each app to have its own ContentProvider? I'm not sure how that would work for our requirements.

If anyone has gone through this kind of situation and could share some insights and recommendations, I'd really appreciate it!

Upvotes: 6

Views: 4033

Answers (2)

juanmeanwhile
juanmeanwhile

Reputation: 2634

AccountManager is meant to solve the exact problem that your are commenting. Here is a good tutorial to work with it: http://blog.udinic.com/2013/04/24/write-your-own-android-authenticator/

Just be sure that you sign all your apps with the same keystore, because this is the only thing that might complicate things (a lot).

Using preferences will lead you into a problem as all that you store in the main thread is not guaranteed to be there in a Service (like a SyncAdapter). There used to be a trick for this in the form of flag (MULTI_SERVICE) but was deprecated in api 23.

ContentProvider is of course possible (its too generic) but AccountManager will help you to cover the corner cases related from refreshing tokens and other interesting stuff.

Upvotes: 3

Joao Sousa
Joao Sousa

Reputation: 4123

ContentProvider is probably your best best. I won't be able to provide the whole code for you to do this, but this is generally how I see it working:

  1. Each app creates a content provider that exposes their own API token;
  2. Each app tries to acquire and query (sequentially until successful) all the other content providers before requesting a login;
  3. If app X is able to acquire and retrieve the token from app Y (via Y's content provider), then store it in app X and use it;

Side notes:

  1. This is very sensitive information, so you should enforce security. Your content providers should only be accessed by other apps signed with the same key, they should have only read permissions and you should create your own custom permission as well.
  2. The content provider does not need to access an sqlite database. It can access whatever your using to store the token (which I hope is stored in a secure way, but I'll leave that to your own judgment)

Useful links:

  1. How to create a custom content provider

  2. How to secure your content provider

  3. Example of content provider that retrieves data from shared preferences;

Upvotes: 5

Related Questions