commonMain.software.momento.kotlin.sdk.auth.CredentialProvider.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of sdk Show documentation
Show all versions of sdk Show documentation
Kotlin client SDK for Momento Serverless Cache
The newest version!
package software.momento.kotlin.sdk.auth
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.Json
import software.momento.kotlin.sdk.exceptions.InvalidArgumentException
import software.momento.kotlin.sdk.internal.utils.decodeBase64
/**
* Contains the information required for a Momento client to connect to and authenticate with
* the Momento service.
*/
public data class CredentialProvider(
val controlEndpoint: String, val cacheEndpoint: String, val apiKey: String
) {
public companion object {
/**
* Creates a [CredentialProvider] from a Momento API key.
* @param apiKey The Momento API key to use for authentication.
* @param controlHost An optional override for the endpoint used for control operations.
* @param cacheHost An optional override for the endpoint used for cache operations.
*/
public fun fromString(
apiKey: String, controlHost: String? = null, cacheHost: String? = null
): CredentialProvider {
try {
val provider = try {
processLegacyKey(apiKey)
} catch (e: Exception) {
processV1Key(apiKey)
}
return provider.copy(
controlEndpoint = controlHost ?: provider.controlEndpoint,
cacheEndpoint = cacheHost ?: provider.cacheEndpoint
)
} catch (e: Exception) {
throw InvalidArgumentException("Invalid API key")
}
}
/**
* Creates a [CredentialProvider] from a Momento API key stored in an environment variable.
* @param envVar The name of the environment variable containing the Momento API key.
* @param controlHost An optional override for the endpoint used for control operations.
* @param cacheHost An optional override for the endpoint used for cache operations.
*/
public fun fromEnvVar(
envVar: String, controlHost: String? = null, cacheHost: String? = null
): CredentialProvider {
val apiKey = System.getenv(envVar) ?: throw InvalidArgumentException("Environment variable $envVar not set")
return fromString(apiKey, controlHost, cacheHost)
}
private val json: Json = Json { ignoreUnknownKeys = true }
private fun processLegacyKey(apiKey: String): CredentialProvider {
val keyParts = apiKey.split(".")
if (keyParts.size != 3) {
throw InvalidArgumentException("Malformed legacy API key")
}
val payloadJson = keyParts[1].decodeBase64() ?: throw InvalidArgumentException("Cannot decode base64")
val payload = json.decodeFromString(payloadJson)
return CredentialProvider(payload.controlEndpoint, payload.cacheEndpoint, apiKey)
}
private fun processV1Key(apiKey: String): CredentialProvider {
val decodedString = apiKey.decodeBase64() ?: throw InvalidArgumentException("Cannot decode base64")
val v1Key = json.decodeFromString(decodedString)
return CredentialProvider("control.${v1Key.host}", "cache.${v1Key.host}", v1Key.apiKey)
}
@Serializable
private data class V1Key(
@SerialName("endpoint") val host: String, @SerialName("api_key") val apiKey: String
)
@Serializable
private data class LegacyKeyPayload(
@SerialName("cp") val controlEndpoint: String, @SerialName("c") val cacheEndpoint: String
)
}
}