OAuth client for Kotlin: integration with providers via ktor-client and kotlinx-serialization

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

OAuth client for Kotlin: integration with providers via ktor-client and kotlinx-serialization



OAuth 2.0 is a standard authorization protocol that allows applications to obtain limited access to user resources without transmitting their credentials. In the Kotlin ecosystem, thanks to JVM compatibility and multiplatform capabilities, you can efficiently implement an OAuth client using modern libraries. In this article, we will look at creating an OAuth client in Kotlin using ktor-client for HTTP requests and kotlinx-serialization for JSON processing.



Main components of an OAuth client

  • HTTP client — ktor-client for sending requests to authorization and resource servers.
  • Serialization — kotlinx-serialization for parsing responses into data classes.
  • Token storage — in-memory or persistent (SharedPreferences, files).
  • State manager — handling authorization code, refresh token, CSRF protection.


Adding dependencies

To work with OAuth in Kotlin, add the following dependencies to build.gradle.kts (or build.gradle):

// build.gradle.ktsdependencies {    implementation("io.ktor:ktor-client-core:2.3.12")    implementation("io.ktor:ktor-client-cio:2.3.12") // engine    implementation("io.ktor:ktor-client-content-negotiation:2.3.12")    implementation("io.ktor:ktor-serialization-kotlinx-json:2.3.12")    implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.7.3")    implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.9.0")}


Basic architecture of an OAuth client

Let's split the logic into three layers:

  • Models (DTO) — data classes for requests/responses.
  • Service — a class managing authorization flows.
  • Client — a wrapper over ktor-client with methods for different grants.


Data models

import kotlinx.serialization.SerialNameimport kotlinx.serialization.Serializable

@Serializabledata class TokenResponse( @SerialName("access_token") val accessToken: String, @SerialName("token_type") val tokenType: String = "Bearer", @SerialName("expires_in") val expiresIn: Long? = null, @SerialName("refresh_token") val refreshToken: String? = null, @SerialName("scope") val scope: String? = null, @SerialName("id_token") val idToken: String? = null // for OpenID Connect)

@Serializabledata class OAuthError( val error: String, @SerialName("error_description") val errorDescription: String? = null)


OAuth2 client

import io.ktor.client.*import io.ktor.client.call.*import io.ktor.client.plugins.contentnegotiation.*import io.ktor.client.request.*import io.ktor.client.statement.*import io.ktor.http.*import io.ktor.serialization.kotlinx.json.*import kotlinx.serialization.json.Json

class OAuth2Client( private val clientId: String, private val clientSecret: String, private val redirectUri: String, private val tokenEndpoint: String, private val authEndpoint: String) { private val httpClient = HttpClient(CIO) { install(ContentNegotiation) { json(Json { ignoreUnknownKeys = true isLenient = true }) } }

// Generate URL for redirect to authorization page fun getAuthorizationUrl(state: String, scope: String = "openid profile email"): String { return "$authEndpoint?response_type=code" + "&client_id=$clientId" + "&redirect_uri=${java.net.URLEncoder.encode(redirectUri, "UTF-8")}" + "&scope=${java.net.URLEncoder.encode(scope, "UTF-8")}

Recommendations