Hi everyone! I’m facing a strange problem with my ...
# ktor
c
Hi everyone! I’m facing a strange problem with my Ktor integration on iOS. I’m using the bearer function of the Auth plugin. The HttpClient on which I installed the plugin is a singleton. When the first call requesting the Bearer token is fired, the loadTokens function is called correctly and the tokens are loaded into the AuthTokenHolder instance managed by the plugin. all the subsequent call using the token are properly created and executed. At a certain point, the user can logout from the app. In that very moment, I’m deleting the tokens saved into the holder using the suggestion I’ve found here.
Copy code
client.plugin(Auth).providers.filterIsInstance<BearerAuthProvider>().first().clearToken()
I’m clearing the tokens so that when the user login again the app doesn’t reuse the tokens loaded in memory during the previous session. If I understood it correclty, clearing the AuthTokenHolder instance is needed for let the condition on this line to be false, so that the code can continue and execute the line 38. Then, alle the subsequent call to loadToken should return on line 35 unless the refreshTokensDeferred variable is set to null. After clearing the holder, I expect the loadTokens function to be called again, so that the code can fetch the new tokens obtained after the new login of the user. Unfortunately, it doesn’t happen and the first call using the Authorization header is using the access token used during the previous session. Can you guys help me on that? Thanks!
a
Untitled.kt
Unfortunately, I cannot reproduce your problem with the above code.
Can you share a code snippet or a sample project to reproduce it?
c
Yes, I’ll do it. I’ll prepare a project that replicates it and I’ll share with you. Unfortunately I can’t share the real code….
I’ve figured out what was causing the issue. I don’t have a clue about it The instance of HttpClient I was using on iOS was sligtly different than the one used on Android. The iOS client had a plugin installed. The plugin was created using the createPlugin function and it was changing the header in the onRequest fun, under certain circumstances Removing the plugin fixed the problem. Now, every time I delete the tokens storage, the app behaves as expected Are you aware of something like that?
Adding some other bit of context Due to some strange behaviour of our api gateway, in case there’s a 401, the WWW-Authenticate header is not accepted by Ktor (Ktor raises an exception saying the header is not well formed) To fix the behaviour we also installed a custom plugin that created a WWW-Authenticate header in a format accepted by Ktor This is the code
Copy code
install("HeaderChanger") { interceptHttpResponse(receivePipeline) }

@InternalAPI
    private fun interceptHttpResponse(receivePipeline: HttpReceivePipeline) {
        receivePipeline.intercept(HttpReceivePipeline.Before) { response ->
            if (response.status.value != Constants.Network.ErrorCodes.UNAUTHORIZED) {
                proceedWith(response)
                return@intercept
            }
            val newResponse = object : HttpResponse() {
                override val call: HttpClientCall = response.call
                override val content: ByteReadChannel = response.content
                override val coroutineContext = response.coroutineContext
                override val headers: Headers = HeadersBuilder().apply {
                    remove(HttpHeaders.WWWAuthenticate)
                    append(HttpHeaders.WWWAuthenticate, "Bearer")
                }.build()
                override val requestTime: GMTDate = response.requestTime
                override val responseTime: GMTDate = response.responseTime
                override val status: HttpStatusCode = response.status
                override val version: HttpProtocolVersion = response.version
            }
            this.proceedWith(newResponse)
        }
    }
How harmful is that?
what do you think @Aleksei Tirman [JB]?
a
Unfortunately, I cannot reproduce this problem with my code above and your interceptor. Can you please adjust my code to make the problem reproducible on the simple case?