Search code examples
androidcsrspongycastleauthenticator

Android Authenticator STORE A CRYPTOGRAPHICALLY SECURE TOKEN


I am authenticating using spongeycastle PKCS10CertificationRequest CSR to a RESTful Certificate Authority. I'm considering using Android Authenticator.

According to: https://stuff.mit.edu/afs/sipb/project/android/docs/training/id-auth/custom_auth.html#Security

It's important to understand that AccountManager is not an encryption service or a keychain. It stores account credentials just as you pass them, in plain text. On most devices, this isn't a particular concern, because it stores them in a database that is only accessible to root. But on a rooted device, the credentials would be readable by anyone with adb access to the device.

With this in mind, you shouldn't pass the user's actual password to AccountManager.addAccountExplicitly(). Instead, you should STORE A CRYPTOGRAPHICALLY SECURE TOKEN that would be of limited use to an attacker.

My questions: I'm not sure what is meant by STORE A CRYPTOGRAPHICALLY SECURE TOKEN in this context. What does that token look like (its type?) in Android Java? And where to store it? in the KeyChain?? Is that token used in any other context other than the pw in addAccountExplicitly()?


Solution

  • If your device has rich input capabilities (so user can input username\password) you may want to consider using something like JWT auth. In this case your app never keeps an actual user password, but sends it to the server only once per authentication session and gets back a JWT (JSON web token). This is a token with some information (for example, with a link to user resource - id or uuid) and TTL parameter securely signed with a secret key. This secret key lives on the server only so nobody outside of your server can generate a valid token.

    So after authentication request you save JWT localy and use it in the "Authorization" header or as a request field (the first option is better because request body can appears in logs) with every API query. You should renew this token before it expires and if it was expired - then ask user to enter his credentials again. From the server side you get a request, validate a token (is it signed with the server secret key and isn't it expired?) and in case of valid token serve a request. You don't even need to keep tokens on server but you might want to do it if you want more control over authentication - for example, if you want to revoke tokens from outside of application workflow.

    There is a list with a lot of libraries for JWT for different languages on the JWT site. For example, for using with Elixir\Phoenix you might want to use Guardian. From Android part in a simple case you don't even need to have a special tools for working with JWT - just put token as a plain text string to the "Authorization" header and send request to the server. But in case you want to get (decode) information your server has put to the token from the app side or check token expiration time - then you'll need to use one of the libraries presented on jwt site.