Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(auth): Add aws-core and AWSCredentialsProvider #2316

Merged
merged 18 commits into from
Mar 14, 2023
Merged
Show file tree
Hide file tree
Changes from 17 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions annotations/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/build
46 changes: 46 additions & 0 deletions annotations/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*
* Copyright 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/

plugins {
id("com.android.library")
id("kotlin-android")
}

apply(from = rootProject.file("configuration/checkstyle.gradle"))
apply(from = rootProject.file("configuration/publishing.gradle"))

group = properties["POM_GROUP"].toString()

android {
kotlinOptions {
moduleName = "com.amplifyframework.annotations"
}
}

dependencies {
implementation(dependency.kotlin.stdlib)
}

afterEvaluate {
// Disables this warning:
// warning: listOf(classfile) MethodParameters attribute
// introduced in version 52.0 class files is ignored in
// version 51.0 class files
// Root project has -Werror, so this warning
// would fail the build, otherwise.
tasks.withType<JavaCompile>().configureEach {
options.compilerArgs.add("-Xlint:-classfile")
}
}
4 changes: 4 additions & 0 deletions annotations/gradle.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
POM_ARTIFACT_ID=annotations
POM_NAME=Amplify Framework for Android - Annotations
POM_DESCRIPTION=Amplify Framework for Android - Annotations for AWS Amplify Libraries
POM_PACKAGING=aar
20 changes: 20 additions & 0 deletions annotations/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License").
You may not use this file except in compliance with the License.
A copy of the License is located at
http://aws.amazon.com/apache2.0
or in the "license" file accompanying this file. This file is distributed
on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
express or implied. See the License for the specific language governing
permissions and limitations under the License.
-->

<manifest package="com.amplifyframework.annotations"
xmlns:android="http://schemas.android.com/apk/res/android">
</manifest>

Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/*
* Copyright 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/

package com.amplifyframework.annotations

/**
* API marked with this annotation is internal to Amplify, and it is not intended to be used outside.
* It could be modified or removed without any notice.
*
* We strongly recommend to not use such API.
*/
@Suppress("DEPRECATION")
@RequiresOptIn(
level = RequiresOptIn.Level.WARNING,
message = "This API is internal to Amplify and should not be used. It could be removed or changed without notice.",
)
@Target(
AnnotationTarget.CLASS,
AnnotationTarget.TYPEALIAS,
AnnotationTarget.FUNCTION,
AnnotationTarget.PROPERTY,
AnnotationTarget.FIELD,
AnnotationTarget.CONSTRUCTOR,
)
public annotation class InternalApiWarning
1 change: 1 addition & 0 deletions aws-analytics-pinpoint/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ group = properties["POM_GROUP"].toString()

dependencies {
implementation(project(":core"))
implementation(project(":aws-core"))

implementation(dependency.androidx.appcompat)
implementation(dependency.aws.pinpointKotlin)
Expand Down
1 change: 1 addition & 0 deletions aws-api-appsync/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ group = properties["POM_GROUP"].toString()

dependencies {
implementation(project(":core"))
implementation(project(":aws-core"))

implementation(dependency.androidx.annotation)
implementation(dependency.androidx.core)
Expand Down
1 change: 1 addition & 0 deletions aws-api/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ group = properties["POM_GROUP"].toString()

dependencies {
api(project(":core"))
api(project(":aws-core"))
implementation(project(":aws-api-appsync"))

implementation(dependency.androidx.appcompat)
Expand Down
1 change: 1 addition & 0 deletions aws-auth-cognito/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ group = properties["POM_GROUP"].toString()

dependencies {
implementation(project(":core"))
implementation(project(":aws-core"))
implementation(dependency.kotlin.coroutines)
implementation(dependency.kotlin.serializationJson)
implementation(dependency.androidx.appcompat)
Expand Down
1 change: 1 addition & 0 deletions aws-core/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/build
50 changes: 50 additions & 0 deletions aws-core/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
* Copyright 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/

plugins {
id("com.android.library")
id("kotlin-android")
}

apply(from = rootProject.file("configuration/checkstyle.gradle"))
apply(from = rootProject.file("configuration/publishing.gradle"))

group = properties["POM_GROUP"].toString()

android {
kotlinOptions {
moduleName = "com.amplifyframework.aws-core"
}
}

dependencies {
implementation(project(":core"))
implementation(dependency.kotlin.stdlib)
implementation(dependency.kotlin.coroutines)

implementation(dependency.aws.credentials)
}

afterEvaluate {
// Disables this warning:
// warning: listOf(classfile) MethodParameters attribute
// introduced in version 52.0 class files is ignored in
// version 51.0 class files
// Root project has -Werror, so this warning
// would fail the build, otherwise.
tasks.withType<JavaCompile>().configureEach {
options.compilerArgs.add("-Xlint:-classfile")
}
}
4 changes: 4 additions & 0 deletions aws-core/gradle.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
POM_ARTIFACT_ID=aws-core
POM_NAME=Amplify Framework for Android - AWS Core
POM_DESCRIPTION=Amplify Framework for Android - AWS Core components and utilities for AWS Amplify Libraries
POM_PACKAGING=aar
20 changes: 20 additions & 0 deletions aws-core/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License").
You may not use this file except in compliance with the License.
A copy of the License is located at
http://aws.amazon.com/apache2.0
or in the "license" file accompanying this file. This file is distributed
on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
express or implied. See the License for the specific language governing
permissions and limitations under the License.
-->

<manifest package="com.amplifyframework.aws.core"
xmlns:android="http://schemas.android.com/apk/res/android">
</manifest>

Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,10 @@
*/
package com.amplifyframework.auth

import com.amplifyframework.annotations.InternalApiWarning
import com.amplifyframework.auth.result.AuthSessionResult

@InternalApiWarning
open class AWSAuthSessionInternal(
@get:JvmName("getSignedIn")
open val isSignedIn: Boolean,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

package com.amplifyframework.auth

import aws.smithy.kotlin.runtime.auth.awscredentials.Credentials
import aws.smithy.kotlin.runtime.time.Instant

/**
Expand Down Expand Up @@ -85,3 +86,12 @@ class AWSTemporaryCredentials(
*/
val expiration: Instant
) : AWSCredentials(accessKeyId, secretAccessKey)

internal fun AWSCredentials.toSdkCredentials(): Credentials {
return Credentials(
accessKeyId = this.accessKeyId,
secretAccessKey = this.secretAccessKey,
sessionToken = (this as? AWSTemporaryCredentials)?.sessionToken,
expiration = (this as? AWSTemporaryCredentials)?.expiration
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/*
* Copyright 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/

package com.amplifyframework.auth

import aws.smithy.kotlin.runtime.auth.awscredentials.Credentials
import aws.smithy.kotlin.runtime.auth.awscredentials.CredentialsProvider
import com.amplifyframework.core.Consumer
import kotlin.coroutines.resume
import kotlin.coroutines.resumeWithException
import kotlin.coroutines.suspendCoroutine

/**
* Customer provided CredentialsProvider implementation that fetches and returns AWSCredentials or a subclass such
* as AWSTemporaryCredentials. For example:
*
* class AWSTemporaryCredentialsProvider: AWSCredentialsProvider<AWSTemporaryCredentials> {
* override fun fetchAWSCredentials(
* onSuccess: Consumer<AWSTemporaryCredentials>,
* onError: Consumer<AuthException>
* ) {
* // customer provided fetch implementation
* }
* }
*/
interface AWSCredentialsProvider<out T : AWSCredentials> {

fun fetchAWSCredentials(
onSuccess: Consumer<@UnsafeVariance T>,
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Want to get thoughts on usage of @UnsafeVariance here, rather than using in. While in is technically correct, it forces customers to use a non obvious Consumer<in AWSTemporaryCredentials in onSuccess and Java users to type Consumer<super ? AWSTemporaryCredentials>.

UnsafeVariance still provides compile time safety here and appears to be commonly used in Kotlin Std Lib, such as List implementation.

onError: Consumer<AuthException>
)
}

fun <T : AWSCredentials> convertToSdkCredentialsProvider(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I dont think this needs to be publicly exposed. If the goal is to pass AWSCredentialsProvider to other components and SDK CredentialsProvider is always accessible through escape hatch, I dont see a reason for this conversion API. Maybe start with non-public and if customers need it we can exposed it in the future.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@div5yesh The reason I exposed is because I don't think we want customers having to use multiple credentials providers, or at least, having to create their own AWSCredentialsProvider and SDKs CredentialsProvider.

Our suggested implementation should be to create a single AWSCredentialsProvider, and when that is needed for the Kotlin SDK escape hatch, they can use this public conversion method.

awsCredentialsProvider: AWSCredentialsProvider<T>
): CredentialsProvider {

return object : CredentialsProvider {
override suspend fun getCredentials(): Credentials {
return suspendCoroutine { continuation ->
awsCredentialsProvider.fetchAWSCredentials(
{ continuation.resume(it.toSdkCredentials()) },
{ continuation.resumeWithException(it) }
)
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,10 @@
package com.amplifyframework.auth

import aws.smithy.kotlin.runtime.auth.awscredentials.CredentialsProvider
import com.amplifyframework.annotations.InternalApiWarning
import com.amplifyframework.core.Consumer

@InternalApiWarning
interface AuthCredentialsProvider : CredentialsProvider {
/**
* Get the identity ID of the currently logged in user if they are registered in identity pools.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ open class CognitoCredentialsProvider : AuthCredentialsProvider {
Amplify.Auth.fetchAuthSession(
{ authSession ->
authSession.toAWSAuthSession()?.awsCredentialsResult?.value?.let {
continuation.resume(it.toCredentials())
continuation.resume(it.toSdkCredentials())
} ?: continuation.resumeWithException(
AuthException(
"Failed to get credentials. " +
Expand Down Expand Up @@ -98,12 +98,3 @@ open class CognitoCredentialsProvider : AuthCredentialsProvider {
private fun AuthSession.toAWSAuthSession(): AWSAuthSessionInternal? {
return this as? AWSAuthSessionInternal
}

private fun AWSCredentials.toCredentials(): Credentials {
return Credentials(
accessKeyId = this.accessKeyId,
secretAccessKey = this.secretAccessKey,
sessionToken = (this as? AWSTemporaryCredentials)?.sessionToken,
expiration = (this as? AWSTemporaryCredentials)?.expiration
)
}
1 change: 1 addition & 0 deletions aws-datastore/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ group = properties["POM_GROUP"].toString()

dependencies {
implementation(project(":core"))
implementation(project(":aws-core"))
implementation(project(":aws-api-appsync"))

implementation(dependency.androidx.appcompat)
Expand Down
1 change: 1 addition & 0 deletions aws-geo-location/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ group = properties["POM_GROUP"].toString()

dependencies {
implementation(project(":core"))
implementation(project(":aws-core"))
implementation(dependency.aws.location)

testImplementation(project(":testutils"))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import android.content.Context
import aws.sdk.kotlin.services.location.LocationClient
import aws.smithy.kotlin.runtime.auth.awscredentials.CredentialsProvider
import com.amplifyframework.AmplifyException
import com.amplifyframework.annotations.InternalApiWarning
import com.amplifyframework.auth.AuthCategory
import com.amplifyframework.auth.CognitoCredentialsProvider
import com.amplifyframework.core.Amplify
Expand Down Expand Up @@ -64,6 +65,7 @@ class AWSLocationGeoPlugin(
configuration.searchIndices!!.default
}

@InternalApiWarning
val credentialsProvider: CredentialsProvider by lazy {
CognitoCredentialsProvider()
}
Expand Down
1 change: 1 addition & 0 deletions aws-predictions-tensorflow/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ group = properties["POM_GROUP"].toString()

dependencies {
implementation(project(":core"))
implementation(project(":aws-core"))
implementation(dependency.androidx.appcompat)
implementation(dependency.tensorflow)

Expand Down
1 change: 1 addition & 0 deletions aws-predictions/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ group = properties["POM_GROUP"].toString()

dependencies {
implementation(project(":core"))
implementation(project(":aws-core"))
implementation(dependency.androidx.appcompat)
implementation(dependency.aws.comprehend)
implementation(dependency.aws.polly)
Expand Down
Loading