改造 - 处理刷新令牌过期

Posted

技术标签:

【中文标题】改造 - 处理刷新令牌过期【英文标题】:Retrofit - Handle refresh token expiration 【发布时间】:2019-09-05 09:16:43 【问题描述】:

当我的应用的 Access Token 过期时,我使用 Refresh Token 通过 Authenticator 类获取新的 Access Token。

我的代码如下:

if (response.code() == 401) 
   Log.d("refresh", "Access token expired")
   val webservice: Webservice = RetrofitClient.makeRetrofitService().create(Webservice::class.java)
   var refreshToken = PreferenceData.getUserLoggedInRefreshToken(App.GetContext()!!)
   var map = generateRequestBody(mapOf("refreshToken" to refreshToken!!))
   var refreshResponse = webservice.refreshToken(map).execute()

   if (refreshResponse != null && refreshResponse.code() == 200) 
      Log.d("refresh", "New access token received")
      var newToken = (refreshResponse.body() as UserLogin).token
      var refreshToken = (refreshResponse.body() as UserLogin).refreshToken
      PreferenceData.setUserLoggedInAccessToken(App.GetContext()!!, newToken)
      PreferenceData.setUserLoggedInRefreshToken(App.GetContext()!!, refreshToken)

      return response.request().newBuilder()
      .header("Authorization", "Bearer $newToken")
      .build();
    

到目前为止一切顺利。 我现在要做的是当我的刷新令牌过期时,我想将用户重定向到应用程序的登录屏幕。但我的问题是,当我打电话时

var refreshResponse = webservice.refreshToken(map).execute()

服务器也返回 401。所以我的问题是我无法判断收到的 401 是由于访问令牌过期还是刷新令牌过期。处理这个问题最合适的方法是什么?

谢谢!

【问题讨论】:

【参考方案1】:

你可以看看AppAuth-android的实现。

    在进行任何调用之前,您可以check that you still have a valid access token,获取其到期时间并将其与来自clock.getCurrentTimeMillis() 的结果进行比较。

    万一访问令牌因其他原因无效(例如访问令牌可以被手动撤销),您可以使用Okhttp Interceptor 来响应 401。

    如果访问令牌过期或者收到401,可以尝试refresh the access token with your refresh token。

    如果刷新令牌不再有效,/token 端点将返回 following error:

HTTP/1.1 400 错误请求 "error":"invalid_request"

    如果您遇到该错误,您可以注销用户并向他发送应用程序的登录屏幕。

希望对你有所帮助。

【讨论】:

所以看来我应该要求服务器返回 400 Bad Request 以便我可以区分失败是因为访问令牌还是刷新令牌过期。我从你的回答中学到的另一件事是,在依赖服务器之前,我们应该先检查客户端令牌的有效性,也许是为了节省 api 的使用。谢谢! 是的,所有可能的错误都在OAuth 2.0 RFC 中定义。在那里您可以看到,当刷新令牌无效、过期或撤销时,服务器必须返回 400invalid_grant 错误代码。关于本地过期检查,它可以让您免于进行不必要的网络调用。 @DavidMiguel 在仓库中检查访问令牌到期的地方,该逻辑可能会失败 - 如果用户更改 android 时间?

以上是关于改造 - 处理刷新令牌过期的主要内容,如果未能解决你的问题,请参考以下文章

有没有一种方法可以使用改造来刷新带有计时器的令牌?

在 Laravel 中处理过期令牌

如何使用带有 OpenId Connect 的刷新令牌在 asp.net 核心中处理过期的访问令牌

通过在改造中透明地发送另一个请求来处理特定错误

刷新刷新令牌

刷新令牌是不是过期,如果过期,何时过期?