Android OAuth2 Bearer令牌最佳做法

问题描述 投票:9回答:2

这个很好的教程非常好地介绍了Android上的帐户身份验证,并通过使用Android的AccountManager

但是,我需要使用承载令牌为OAuth2 API创建客户端应用程序以进行身份​​验证。 在获得令牌时,我收到了它的到期时间戳,但我不清楚存储的位置以及如何正确使用它。 问题是,如果我不想不必要地去服务器,应用程序会意识到,只有在请求任何随机资源时从服务器收到HTTP 401错误后,承载才会变为无效。 那么,解决这个问题的最佳做法是什么:

  1. 我的代码中的每个网络请求都应该具有重试机制,以防承载令牌在此期间变为无效吗? 在捕获异常时我可能invalidateAuthToken并重试。
  2. 同步适配器能以某种方式帮助吗?

由于我是Android开发的新手,我希望解决方案也可能与我预期的完全不同。

如果它是相关的,我打算使用Volley进行服务器通信。

android oauth-2.0 accountmanager android-syncadapter android-volley
2个回答
9
投票

经过一番调查后我发现了自己的答案:

  1. 是的,调用AccountManager#invalidateAuthToken将删除上次保存的身份验证令牌(OAuth2案例中的访问令牌),并期望您在下一个AccountAuthenticator#getAuthToken调用中检测到该AccountAuthenticator#getAuthToken 。 例如,以下是该方法的代码:

     @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's 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; } 

    我还收到了问题中提到的博客文章的作者的确认

  2. SyncAdapter无法直接帮助,因为它们的真正目的是异步(对于开发人员)和透明地(对于用户)从网络获取数据。 他们只使用AbstractAccountAuthenticator并在适当的地方调用其方法。


1
投票

之前我遇到了同样的问题,并将此库设置为Android中的handel OAuth2。 但该库是Retrofit的扩展,它简化了对OAuth 2提供程序进行身份验证的过程,但您仍然可以使用它。

© www.soinside.com 2019 - 2024. All rights reserved.