Android OAuth2 Token Usage Guidelines

This good tutorial is a very good introduction to authenticating an Android account and using it using the Android AccountManager .

However, I need to create a client application for the OAuth2 API using the Bearer token for authentication. When I receive a token, I get a timestamp for its expiration, but I do not understand where to store it and how to use it correctly. The problem is that if I do not want to have unnecessary trips to the server, the application will understand that the media became invalid only after it received an HTTP 401 error from the server when requesting any random resource. So what is the best practice to solve this problem:

  • Should every network request in my code have a retry mechanism in case the carrier token has become invalid? I probably invalidateAuthToken if you catch an exception and try again.
  • Can the sync adapter help here somehow?

Since I am new to Android development, I expect the solution to also be something completely different than I expect.

If relevant, I intend to use Volley to communicate with the server.

+8
android android-volley accountmanager android-syncadapter
source share
2 answers

I found out my own answers after a little investigation:

  • Yes, a call to AccountManager#invalidateAuthToken deletes the last stored authentication token (access token in the case of OAuth2) and expects you to find this on the next call to AccountAuthenticator#getAuthToken . For example, the following code is used for my method:

     @Override public Bundle getAuthToken(AccountAuthenticatorResponse response, Account account, String authTokenType, Bundle options) throws NetworkErrorException { // Extract the username and password from the Account Manager, and ask // for an appropriate AuthToken. final AccountManager am = AccountManager.get(mContext); String authToken = am.peekAuthToken(account, authTokenType); // EXTRA: I am also storing the OAuth2 refresh token in the AccountManager Map<String, String> refreshResult = null; String refreshToken = am.getUserData(account, KEY_REFRESH_TOKEN); if (TextUtils.isEmpty(authToken) && !TextUtils.isEmpty(refreshToken)) { // lets try to refresh the token // EXTRA: AuthenticationProvider is my class for accessing the authentication server, getting new access and refresh token based on the existing refresh token refreshResult = AuthenticationProvider. refreshAccessToken(am.getUserData(account, KEY_REFRESH_TOKEN)); } // If we get a result from the refresh - we return it if (!refreshResult.isEmpty()) { authToken = refreshResult.get(AccountManager.KEY_AUTHTOKEN); // EXTRA: new refresh token used only in OAuth2 refreshToken = refreshResult.get(KEY_REFRESH_TOKEN); final Bundle result = new Bundle(); result.putString(AccountManager.KEY_ACCOUNT_NAME, account.name); result.putString(AccountManager.KEY_ACCOUNT_TYPE, account.type); // store the new tokens in the system am.setAuthToken(account, authTokenType, authToken); am.setUserData(account, KEY_REFRESH_TOKEN, refreshToken); result.putString(AccountManager.KEY_AUTHTOKEN, refreshResult.get(AccountManager.KEY_AUTHTOKEN)); result.putString(KEY_REFRESH_TOKEN, refreshResult.get(KEY_REFRESH_TOKEN)); return result; } // If we get here, then we couldn't access the user password - so we // need to re-prompt them for their credentials. We do that by creating // an intent to display our AuthenticatorActivity. final Intent intent = new Intent(mContext, LoginActivity.class); intent.putExtra(AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE, response); final Bundle bundle = new Bundle(); bundle.putParcelable(AccountManager.KEY_INTENT, intent); return bundle; } 

    I also received confirmation from the author of the blog post mentioned in the question.

  • SyncAdapter cannot help directly, since their true goal is to receive data from the network asynchronously (for the developer) and transparently (for the user). They simply use the AbstractAccountAuthenticator and call its methods if necessary.

+9
source share

I have already encountered the same problem and am doing this library to pass OAuth2 to Android. but the library is an extension for Retrofit, which simplifies the authentication process with the OAuth 2 provider, but you can use it anyway.

+1
source share

All Articles