diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/track/myanimelist/MyAnimeListInterceptor.kt b/app/src/main/java/eu/kanade/tachiyomi/data/track/myanimelist/MyAnimeListInterceptor.kt index da1768178..16313520c 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/track/myanimelist/MyAnimeListInterceptor.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/track/myanimelist/MyAnimeListInterceptor.kt @@ -20,23 +20,9 @@ class MyAnimeListInterceptor(private val myanimelist: MyAnimeList, private var t } // Refresh access token if expired if (oauth != null && oauth!!.isExpired()) { - val newOauth = runCatching { - val oauthResponse = chain.proceed(MyAnimeListApi.refreshTokenRequest(oauth!!)) - - if (oauthResponse.isSuccessful) { - oauthResponse.parseAs() - } else { - oauthResponse.close() - null - } - } - - if (newOauth.getOrNull() == null) { - throw IOException("Failed to refresh the access token") - } - - setAuth(newOauth.getOrNull()) + setAuth(refreshToken(chain)) } + if (oauth == null) { throw IOException("No authentication token") } @@ -46,7 +32,26 @@ class MyAnimeListInterceptor(private val myanimelist: MyAnimeList, private var t .addHeader("Authorization", "Bearer ${oauth!!.access_token}") .build() - return chain.proceed(authRequest) + val response = chain.proceed(authRequest) + val tokenIsExpired = response.headers["www-authenticate"] + ?.contains("The access token expired") ?: false + + // Retry the request once with a new token in case it was not already refreshed + // by the is expired check before. + if (response.code == 401 && tokenIsExpired) { + response.close() + + val newToken = refreshToken(chain) + setAuth(newToken) + + val newRequest = originalRequest.newBuilder() + .addHeader("Authorization", "Bearer ${newToken.access_token}") + .build() + + return chain.proceed(newRequest) + } + + return response } /** @@ -58,4 +63,23 @@ class MyAnimeListInterceptor(private val myanimelist: MyAnimeList, private var t this.oauth = oauth myanimelist.saveOAuth(oauth) } + + private fun refreshToken(chain: Interceptor.Chain): OAuth { + val newOauth = runCatching { + val oauthResponse = chain.proceed(MyAnimeListApi.refreshTokenRequest(oauth!!)) + + if (oauthResponse.isSuccessful) { + oauthResponse.parseAs() + } else { + oauthResponse.close() + null + } + } + + if (newOauth.getOrNull() == null) { + throw IOException("Failed to refresh the access token") + } + + return newOauth.getOrNull()!! + } }