Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

OkHttp Authenticator looping after successful refresh token request

I've implemented class extending okhttp3.Authenticator along with Retrofit 2 for handling 401 errors inside my android app. It should call refreshToken request and then if it succeeds, recall desired request with new access token. The problem is that after successful refresh token obtain, my TokenAuthenticator... Refreshes token again and again until some limit is reached. Do you have any clue what is going on?

TokenAuthenticator class:

class TokenAuthenticator : Authenticator {

    private val notLoggedResponseCode = 401
    private val successResponseCode = 200
    private val refreshTokenGrantType = "refresh_token"

    override fun authenticate(route: Route?, response: okhttp3.Response?): Request? {

        if (response?.code() == notLoggedResponseCode) {

            val refreshTokenResponse: Response<Authorization> = RestController
                    .getInstance()
                    .basicRetrofit
                    .create(AuthRepository::class.java)
                    .refreshToken(
                            Credentials.basic(BuildConfig.CLIENT_ID, BuildConfig.CLIENT_SECRET),
                            refreshTokenGrantType,
                            UserSession.getInstance().authorization?.refreshToken!!)
                    .execute()



            return if (refreshTokenResponse.code() == successResponseCode) {
                UserSession.getInstance().authorization = refreshTokenResponse.body() //updating token
                UserSession.getInstance().saveAuthorizationData()

                // Every time flow is here, so new access token is obtained.
                // But somehow it starts refresh procedure again... 
                response
                        .request()
                        .newBuilder()
                        .build()
            } else {
                null
            }
        } else {
            return null
        }
    }
}

Method initializing OkHttp client for retrofit:

    private fun initBaseOkHttpClientBuilder(): OkHttpClient.Builder {
        val logging = HttpLoggingInterceptor().apply {
            this.level = HttpLoggingInterceptor.Level.BODY
        }

        return OkHttpClient.Builder()
                .connectTimeout(connectionTimeout, TimeUnit.SECONDS)
                .readTimeout(connectionTimeout, TimeUnit.SECONDS)
                .writeTimeout(connectionTimeout, TimeUnit.SECONDS)
                .addInterceptor(logging)
                .authenticator(TokenAuthenticator())
                .addInterceptor(OAuth2Interceptor())
    }
like image 685
J.fr Avatar asked Sep 20 '18 12:09

J.fr


1 Answers

When you get the refresh token, you need it to pass to the new request in the header. Something like response.request().newBuilder().header("Authorization", "bearer " + bearer).build()

like image 139
karandeep singh Avatar answered Nov 15 '22 16:11

karandeep singh