Shouldn’t Android AccountManager Store OAuth Tokens on a Per-App/UID Basis?

Is this a valid/practical security concern?

For the official Client A, my OAuth2 provider may issue a “super” type/scope token which grants access to both public and private pieces of my API

In the general case, you could never rely on an auth token given to a user remaining secret from that user. For example – the user could be running a rooted phone, and read off the token, gaining access to your private API. Ditto if the user’s system was compromised (the attacker could read off the token in this case).

Put another way, there’s no such thing as a “private” API that is at the same time accessible to any authenticated user, so it’s reasonable for Android to ignore this security by obscurity goal in its design.

a malicious app … could obtain access to my app’s stored OAuth2 token

For the malicious app case, it begins to sound more reasonable that a malicious app shouldn’t be able to use the client’s token, as we expect Android’s permission system to provide isolation of malicious apps (provided the user read / cared about the permissions they accepted when they installed it). However, as you say the user needed to accept an (Android system provided) access request for the app to use your token.

Given that, the Android solution seems OK – apps can’t silently use a user’s authentication without asking, but the user can explicitly allow apps to re-use a previous authentication to a service, which is convenient for the user.

Possible Solutions Review

“Secret” authTokenType … does not seem very secure

Agreed – it’s just another layer of security through obscurity; it sounds like any app wishing to share your authentication would have had to look up what the authTokenType was anyway, so adopting this approach just makes it a bit more awkward for this hypothetical app developer.

Send client ID/secret w/ OAuth2 token … [to] verify server-side that the app is the authorized client

This isn’t possible in the general case (all the server gets is a series of messages in a protocol – the code that generated those messages can’t be determined). In this specific instance, it might protect against the more limited threat of a (non-root) alternative client / malicious app – I’m not familiar enough with the AccountManager to comment (ditto for your custom auth tokens solutions).

Suggestion

You described two threats – malicious apps that a user doesn’t want to have access to their account, and alternative clients that you (the developer) doesn’t want using parts of the API.

  • Malicious apps: Consider how sensitive the service you are providing is, and if it’s not more sensitive than e.g. Google / twitter accounts, just rely on Android’s protections (permissions on install, Access Request screen). If it is more sensitive, consider whether your constraint of utilizing Android’s AccountManager is appropriate. To strongly protect the user against malicious use of their account, try two factor authentication for dangerous actions (c.f. adding a new recipient’s account details in online banking).

  • Alternative clients: don’t have a secret API that attempts to only be accessible to an official client; people will get around this. Ensure all your public facing APIs are secure no matter what (future) client the user is using.

Leave a Comment

Hata!: SQLSTATE[HY000] [1045] Access denied for user 'divattrend_liink'@'localhost' (using password: YES)