Created
June 25, 2019 11:27
-
-
Save zern3w/3867522f4992e02f177e5a28fc2fde40 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import android.os.SystemClock | |
import android.util.Log | |
import okhttp3.Interceptor | |
import okhttp3.Response | |
import java.io.IOException | |
class RequestInterceptor(private val tokenStore: TokenStore) : Interceptor { | |
private val oauthService by lazy { ServiceGenerator.createAuthService() } | |
private var isRefreshing = false | |
@Throws(IOException::class) | |
override fun intercept(chain: Interceptor.Chain): Response { | |
val response = chain.proceed(chain.request()) | |
// Checking for unauthorized | |
if (response.code() == 401) { | |
Log.d(javaClass.simpleName, "Unauthorized request was intercepted") | |
// Wait until refresh token is finished | |
if (isRefreshing){ | |
Log.d(javaClass.simpleName, "Token is refreshing ...") | |
do { | |
Log.d(javaClass.simpleName, "Sleep for ${SLEEP_TIME/1000} seconds ...") | |
SystemClock.sleep(SLEEP_TIME) | |
} while (isRefreshing) | |
return chain.proceed(chain.request()) | |
} | |
val refreshToken = tokenStore.getRefreshToken() | |
if (!refreshToken.isNullOrEmpty()){ | |
// Perform synchronous refresh token | |
val refreshResponse = refreshToken(refreshToken!!) | |
if (refreshResponse != null) { | |
when { | |
// NetworkInterceptor will take care of adding authorization header after refreshing token has finished | |
refreshResponse.code() == 200 -> return chain.proceed(chain.request()) | |
refreshResponse.code() == 401 -> logout() | |
else -> return refreshResponse | |
} | |
} | |
} | |
} | |
return response | |
} | |
private fun refreshToken(refreshToken: String): Response? { | |
isRefreshing = true | |
var failedAttempt = 0 | |
var response: Response? = null | |
do { | |
Log.d(javaClass.simpleName, "Refreshing Token") | |
val call = oauthService.refreshToken("refresh_token", refreshToken) | |
try { | |
val requestResponse = call.execute() | |
response = requestResponse.raw() | |
if (requestResponse.isSuccessful){ | |
var accessToken = requestResponse.body() | |
if (accessToken != null){ | |
Log.d(javaClass.simpleName, "Refresh Token success") | |
setActiveToken(accessToken.accessToken, accessToken.refreshToken) | |
isRefreshing = false | |
return response | |
}else{ | |
failedAttempt += 1 | |
} | |
}else{ | |
failedAttempt += 1 | |
} | |
} catch (e: IOException) { | |
failedAttempt += 1 | |
e.printStackTrace() | |
} | |
} while (failedAttempt < MAX_ATTEMPT) | |
isRefreshing = false | |
return response | |
} | |
private fun setActiveToken(accessToken: String?, refreshToken: String?) { | |
if (!accessToken.isNullOrEmpty() && !refreshToken.isNullOrEmpty()) { | |
tokenStore.saveToken(accessToken!!) | |
tokenStore.saveRefreshToken(refreshToken!!) | |
tokenStore.notifiyTokenUpdate(accessToken, refreshToken) | |
} | |
} | |
private fun logout() { | |
Log.d(javaClass.simpleName, "Refresh Token failed, perform force logout") | |
} | |
companion object { | |
private const val MAX_ATTEMPT = 3 | |
private const val SLEEP_TIME: Long = 3*1000 // 3 Seconds | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment