Android 后的 Oauth2 刷新令牌更新
Oauth2 refresh token renewal in Android
我正在开发一个 Android 应用程序,该应用程序使用 Oauth2 令牌获取授权以访问受保护的资源。我使用第三方平台作为身份验证服务器(使用 OpenId Connect)。基本上我的问题是我想处理过期的刷新令牌。
当前场景
我有一个 NetUtils
class,它就像一个单例,使用安全的休息模板管理我的所有请求。该其余模板使用请求包装器为每个请求注入所需的授权 header。 NetUtils
class 处理令牌和超时,将它们保存在用户首选项中并在需要时刷新它们。
但是,当刷新令牌本身过期时就会出现问题。当我使用授权代码流时,我需要打开一个 WebView 并将用户重定向到登录页面,但是当 NetUtils class 确定刷新令牌已过期时我注意到了它。理想情况下,应用程序将启动一个 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 目前正在应用程序中进行硬编码(尽管客户端凭证授予不是意味着在生产中启用,因此仍然需要提供用户名和密码来检索令牌)。
这里的最佳做法是什么?
我想我无法建议您如何在 Java 中编写代码,但我在 PHP 中创建应用程序时也遇到了 refresh_token 的一些问题,所以也许我的想法会有所帮助你有东西。
起初我一直在寻找永不过期的 refresh_token(比如 Google API),所以我什至可以对其进行硬编码并在我想创建新的 [=] 时使用31=]。无论如何,在 oAuth2 中真的很难做到。所以我在这里找到了关于这个问题的有趣观点:
Why do access tokens expire?
它向我展示了使用 refresh_token 的另一种方式。我在我的 oAuth 服务上设置了它生成的 returns 一个新的 refresh_token 每次我使用 refresh_token 获得一个新的 access_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 令牌获取授权以访问受保护的资源。我使用第三方平台作为身份验证服务器(使用 OpenId Connect)。基本上我的问题是我想处理过期的刷新令牌。
当前场景
我有一个 NetUtils
class,它就像一个单例,使用安全的休息模板管理我的所有请求。该其余模板使用请求包装器为每个请求注入所需的授权 header。 NetUtils
class 处理令牌和超时,将它们保存在用户首选项中并在需要时刷新它们。
但是,当刷新令牌本身过期时就会出现问题。当我使用授权代码流时,我需要打开一个 WebView 并将用户重定向到登录页面,但是当 NetUtils class 确定刷新令牌已过期时我注意到了它。理想情况下,应用程序将启动一个 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 目前正在应用程序中进行硬编码(尽管客户端凭证授予不是意味着在生产中启用,因此仍然需要提供用户名和密码来检索令牌)。
这里的最佳做法是什么?
我想我无法建议您如何在 Java 中编写代码,但我在 PHP 中创建应用程序时也遇到了 refresh_token 的一些问题,所以也许我的想法会有所帮助你有东西。
起初我一直在寻找永不过期的 refresh_token(比如 Google API),所以我什至可以对其进行硬编码并在我想创建新的 [=] 时使用31=]。无论如何,在 oAuth2 中真的很难做到。所以我在这里找到了关于这个问题的有趣观点:
Why do access tokens expire?
它向我展示了使用 refresh_token 的另一种方式。我在我的 oAuth 服务上设置了它生成的 returns 一个新的 refresh_token 每次我使用 refresh_token 获得一个新的 access_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,我觉得他应该重新给自己授权。