diff --git a/codegen/smithy-kotlin-codegen/src/main/kotlin/software/amazon/smithy/kotlin/codegen/core/RuntimeTypes.kt b/codegen/smithy-kotlin-codegen/src/main/kotlin/software/amazon/smithy/kotlin/codegen/core/RuntimeTypes.kt index 53fb49c71..1cbf3b407 100644 --- a/codegen/smithy-kotlin-codegen/src/main/kotlin/software/amazon/smithy/kotlin/codegen/core/RuntimeTypes.kt +++ b/codegen/smithy-kotlin-codegen/src/main/kotlin/software/amazon/smithy/kotlin/codegen/core/RuntimeTypes.kt @@ -374,6 +374,8 @@ object RuntimeTypes { val BearerTokenAuthScheme = symbol("BearerTokenAuthScheme") val BearerTokenProviderConfig = symbol("BearerTokenProviderConfig") val BearerTokenProvider = symbol("BearerTokenProvider") + val BearerToken = symbol("BearerToken") + val EnvironmentBearerTokenProvider = symbol("EnvironmentBearerTokenProvider") val reprioritizeAuthOptions = symbol("reprioritizeAuthOptions") } diff --git a/runtime/auth/http-auth/api/http-auth.api b/runtime/auth/http-auth/api/http-auth.api index 709166a39..d47a5a9c7 100644 --- a/runtime/auth/http-auth/api/http-auth.api +++ b/runtime/auth/http-auth/api/http-auth.api @@ -59,6 +59,12 @@ public final class aws/smithy/kotlin/runtime/http/auth/BearerTokenSigner : aws/s public abstract interface class aws/smithy/kotlin/runtime/http/auth/CloseableBearerTokenProvider : aws/smithy/kotlin/runtime/http/auth/BearerTokenProvider, java/io/Closeable { } +public final class aws/smithy/kotlin/runtime/http/auth/EnvironmentBearerTokenProvider : aws/smithy/kotlin/runtime/http/auth/BearerTokenProvider { + public fun (Ljava/lang/String;Laws/smithy/kotlin/runtime/util/PlatformProvider;)V + public synthetic fun (Ljava/lang/String;Laws/smithy/kotlin/runtime/util/PlatformProvider;ILkotlin/jvm/internal/DefaultConstructorMarker;)V + public fun resolve (Laws/smithy/kotlin/runtime/collections/Attributes;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; +} + public final class aws/smithy/kotlin/runtime/http/auth/ReprioritizeAuthOptionsKt { public static final fun reprioritizeAuthOptions (Ljava/util/List;Ljava/util/List;)Ljava/util/List; } diff --git a/runtime/auth/http-auth/common/src/aws/smithy/kotlin/runtime/http/auth/EnvironmentBearerTokenProvider.kt b/runtime/auth/http-auth/common/src/aws/smithy/kotlin/runtime/http/auth/EnvironmentBearerTokenProvider.kt new file mode 100644 index 000000000..ffe37b60b --- /dev/null +++ b/runtime/auth/http-auth/common/src/aws/smithy/kotlin/runtime/http/auth/EnvironmentBearerTokenProvider.kt @@ -0,0 +1,29 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ +package aws.smithy.kotlin.runtime.http.auth + +import aws.smithy.kotlin.runtime.collections.Attributes +import aws.smithy.kotlin.runtime.collections.emptyAttributes +import aws.smithy.kotlin.runtime.time.Instant +import aws.smithy.kotlin.runtime.util.PlatformProvider + +/** + * A [BearerTokenProvider] that extracts the bearer token from the target environment variable. + */ +public class EnvironmentBearerTokenProvider( + private val key: String, + private val platform: PlatformProvider = PlatformProvider.System, +) : BearerTokenProvider { + override suspend fun resolve(attributes: Attributes): BearerToken { + val bearerToken = platform.getenv(key) + ?: error("$key environment variable is not set") + + return object : BearerToken { + override val token: String = bearerToken + override val attributes: Attributes = emptyAttributes() + override val expiration: Instant? = null + } + } +} diff --git a/runtime/auth/http-auth/common/test/aws/smithy/kotlin/runtime/http/auth/EnvironmentBearerTokenProviderTest.kt b/runtime/auth/http-auth/common/test/aws/smithy/kotlin/runtime/http/auth/EnvironmentBearerTokenProviderTest.kt new file mode 100644 index 000000000..e98e8083d --- /dev/null +++ b/runtime/auth/http-auth/common/test/aws/smithy/kotlin/runtime/http/auth/EnvironmentBearerTokenProviderTest.kt @@ -0,0 +1,35 @@ +package aws.smithy.kotlin.runtime.http.auth + +import aws.smithy.kotlin.runtime.collections.emptyAttributes +import aws.smithy.kotlin.runtime.util.TestPlatformProvider +import kotlinx.coroutines.test.runTest +import kotlin.test.Test +import kotlin.test.assertEquals +import kotlin.test.assertFailsWith + +class EnvironmentBearerTokenProviderTest { + @Test + fun testResolveWithValidToken() = runTest { + val provider = EnvironmentBearerTokenProvider( + "TEST_TOKEN", + TestPlatformProvider(mutableMapOf("TEST_TOKEN" to "test-bearer-token")), + ) + + val token = provider.resolve() + + assertEquals("test-bearer-token", token.token) + } + + @Test + fun testResolveWithMissingToken() = runTest { + val provider = EnvironmentBearerTokenProvider( + "MISSING_TEST_TOKEN", + TestPlatformProvider(mutableMapOf()), + ) + + val exception = assertFailsWith { + provider.resolve(emptyAttributes()) + } + assertEquals("MISSING_TEST_TOKEN environment variable is not set", exception.message) + } +}