Ktor client, how correctly set access token after receiving it?

64 Views Asked by At

Here is my ktor client setup

@OptIn(ExperimentalSerializationApi::class)
@Singleton
@Provides
fun provideHttpClient(
    localService: LocalService,
): HttpClient {

    val chuckerInterceptor = ChuckerInterceptor.Builder(App.appContext)
        .collector(ChuckerCollector(App.appContext))
        .maxContentLength(250000L)
        .redactHeaders(emptySet())
        .alwaysReadResponseBody(false)
        .build()

    val okhttpEngine = OkHttp.create {
        addInterceptor(chuckerInterceptor)
    }
 

    return HttpClient(okhttpEngine) {

        install(ContentNegotiation) {
            json(
                Json {
                    prettyPrint = true
                    isLenient = true
                    useAlternativeNames = true
                    ignoreUnknownKeys = true
                    encodeDefaults = false
                    explicitNulls = false

                }
            )
        }

        install(HttpTimeout) {
            requestTimeoutMillis = 10_000
            connectTimeoutMillis = 10_000
            socketTimeoutMillis = 10_000
        }

        install(Logging) {
            logger = object : Logger {
                override fun log(message: String) {
                    Log.v("Logger Ktor =>", message)
                }
            }
            level = LogLevel.ALL
        }

        install(ResponseObserver) {
            onResponse { response ->
                Log.d("HTTP status:", "${response.status.value}")
            }
        }

        install(DefaultRequest) {
            header(HttpHeaders.ContentType, ContentType.Application.Json)
          
        }

        defaultRequest {

            contentType(ContentType.Application.Json)
            accept(ContentType.Application.Json)
          
        }

        install(Auth) {
            bearer {
                refreshTokens {

                    val token = client.get {
                        markAsRefreshTokenRequest()
                        url(BASE_URL + REFRESH_TOKEN)
                        parameter("refreshToken", localService.getRefreshToken())
                    }.body<AuthResponseDto>()
                    BearerTokens(
                        accessToken = token.accessToken.token,
                        refreshToken = token.refreshToken.token
                    )
                }
                loadTokens {

                    BearerTokens(
                        accessToken = localService.getAccessToken().orEmpty(),
                        refreshToken = localService.getRefreshToken().orEmpty(),
                    )
                }
            }
        }
    }
}

The problem is according to access token. When i receive access and refresh tokens after success auth, i saved it to local storage (DataStore). Then when i try to make next request, there no token in request, but when i reopen application all is ok. As i understood ktor cannot runtime get token from local storage and update client after i have saved it ? How to solve it ?

1

There are 1 best solutions below

0
JoeyOggie On

According to gpunto's question (Correct way to retrigger loadTokens in Ktor client), one solution is to manually retrieve BearerAuthProvider from the HttpClient and clear the token yourself like in the following snippet:

httpClient.plugin(Auth).providers
.filterIsInstance<BearerAuthProvider>()
.first().clearToken()