Android中的Oauth2刷新令牌更新
Posted
技术标签:
【中文标题】Android中的Oauth2刷新令牌更新【英文标题】:Oauth2 refresh token renewal in Android 【发布时间】:2017-03-29 14:29:16 【问题描述】:我正在开发一个 android 应用程序,它使用 Oauth2 令牌来获得授权以访问安全资源。我使用第三方平台作为身份验证服务器(使用 OpenId Connect)。基本上我的问题是我想处理过期的刷新令牌。
当前情景
我有一个NetUtils
类,它的作用类似于单例,并使用安全的休息模板管理我的所有请求。该 rest 模板使用请求包装器为每个请求注入所需的 Authorization 标头。 NetUtils
类处理令牌和超时,将它们保存在用户首选项中并在需要时刷新它们。
但是,当刷新令牌本身过期时,问题就出现了。当我使用授权代码流时,我需要打开一个 WebView 并将用户重定向到登录页面,但是当 NetUtils 类确定刷新令牌已过期时,我注意到它。理想情况下,应用程序会启动一个 WebView,用户将再次登录并执行存储的请求。这是我刷新访问令牌的代码:
private AccessToken refreshToken(String idClient, String clientSecret, AccessToken accessToken)
MultiValueMap<String, String> clientAuthenticationForm = new LinkedMultiValueMap<>();
clientAuthenticationForm.add("grant_type", "refresh_token");
clientAuthenticationForm.add("refresh_token", accessToken.getRefreshToken());
clientAuthenticationForm.add("client_id", idClient);
clientAuthenticationForm.add("client_secret", clientSecret);
try
long lastClientRefresh = mPrefs.getLong(Preferences.LAST_LOGIN_TIME, Long.MIN_VALUE);
boolean refreshTokenExpired = lastClientRefresh
+ TimeUnit.SECONDS.toMillis(accessToken.getRefreshExpiresIn()) < System
.currentTimeMillis();
if (!refreshTokenExpired)
return regularRestTemplate
.postForEntity(tokenUrl(), clientAuthenticationForm, AccessToken.class)
.getBody();
else
//How to cope with this?
return null;
catch (Exception ex)
Log.e(TAG, ex.getMessage(), ex);
throw ex;
其他选择
例如,其他选择是使刷新令牌长期存在并在每次应用启动时刷新它。我不得不提一下,client_id 和 client_secret 目前正在应用程序中进行硬编码(尽管客户端凭据授予并不意味着在生产中启用,因此仍然需要提供用于检索令牌的用户名和密码)。
这里的最佳做法是什么?
【问题讨论】:
【参考方案1】:我想我不能建议你如何用 Java 编写代码,但是我在用 php 创建应用程序时也遇到了 refresh_token 的一些问题,所以也许我的想法会对你有所帮助。
起初我在寻找永不过期的 refresh_token(就像在 Google API 中一样),所以我什至可以对其进行硬编码,并在我想创建一个新的 access_token 时使用它。无论如何,在 oAuth2 中真的很难做到。所以我在这里找到了关于这个问题的有趣观点:
Why do access tokens expire?
它向我展示了使用 refresh_token 的其他方式。我已经设置了我的 oAuth 服务,每次我使用 refresh_token 获取新的 access_token 时,它都会生成并返回一个新的 refresh_token。那部分对我帮助最大:
https://bshaffer.github.io/oauth2-server-php-docs/grant-types/refresh-token/
我们得到了类似的东西:
$server = new OAuth2\Server($storage, array(
'always_issue_new_refresh_token' => true, // this part
'refresh_token_lifetime' => 2419200,
));
在这种情况下,我有一个长期存在的 refresh_token,我可以将它存储在某个地方,当我需要它时,我将使用它来获取新的 access_token,但响应也会为我提供一个新的 refresh_token,我可以再次存储它并在以后使用它用于获取新的 access_token。
因此,在您的情况下,我认为最好的方法是每次使用 refresh_token 请求 access_token 时继续生成 refresh_token。如果用户长时间不使用你的APP,我认为他应该重新授权自己。
【讨论】:
感谢您的回复!这或多或少是我最终实现的以上是关于Android中的Oauth2刷新令牌更新的主要内容,如果未能解决你的问题,请参考以下文章
刷新的 OAuth2 令牌具有无效签名 (Azure AD OAuth2)
无法在跨客户端谷歌 oauth2.0 中交换访问令牌和刷新令牌的授权码