Hi, I am very new to the ktor client. What I am t...
# ktor
h
Hi, I am very new to the ktor client. What I am trying to do is using it for an integration test using oauth. Using the manual way to add a
Authorization
header manually works, but I need to automate it using clientCredentials flow and client-id and client-secret. So far when I google about it, I just get how to set up oauth with ktor on the server-side, not on the client side. Has anybody done so and can give me a code example or a link where I can find help?
n
i think there is no such feature for ktor-client yet, you will have to send the requests to the oauth2 endpoint yourself
i also stumbled over this: but i do not speak norwegian: https://github.com/navikt/dusseldorf-ktor/tree/master/dusseldorf-oauth2-client
h
I see. so I did find a workaround that works for me, as I am doing it for testing I have to get the token once and then reuse it. But I guess I will put a feature request in, thanks Unfortunately I do not speak norweigan either 😓
n
if you can share your code though.. i think that would be useful for me later
h
Copy code
import io.ktor.client.HttpClient
import io.ktor.client.engine.apache.Apache
import io.ktor.client.features.json.JsonFeature
import io.ktor.client.request.accept
import io.ktor.client.request.forms.FormDataContent
import io.ktor.client.request.header
import <http://io.ktor.client.request.post|io.ktor.client.request.post>
import io.ktor.http.ContentType
import io.ktor.http.parametersOf
import io.ktor.utils.io.core.toByteArray
import kotlinx.coroutines.runBlocking
import java.util.*

var token: String = ""
private val clientId: String? = System.getenv("CLIENT_ID")
private val clientSecret: String? = System.getenv("CLIENT_SECRET")

private val client = HttpClient(Apache) {
    install(JsonFeature)
}

fun getAccessToken(): String {
    if (token.isBlank()) {
        retrieveToken()
    }
    return token
}

fun retrieveToken(): String {
    val data = runBlocking {
        <http://client.post|client.post><Map<String, String>>("<access-token-endpoint>") {
            header("Authorization", constructBasicAuthValue())
            accept(ContentType.Application.Json)
            body = FormDataContent(parametersOf("grant_type" to listOf("client_credentials")))
        }
    }
    token = data["access_token"] ?: throw IllegalStateException("Error retrieving access token")
    return token
}

private fun constructBasicAuthValue(): String {
    val authString = "$clientId:$clientSecret"
    val authBuf = Base64.getEncoder().encodeToString(authString.toByteArray())

    return "Basic $authBuf"
}
For me for some reason the
Auth
Feature did not work, so I copy/pasted the function in the bottom from there. I basically created an Extensions file and added those methods there. not yet polished, but maybe good enough for now 🙂
❤️ 1