Skip to content

Commit 038707a

Browse files
authored
feat(events): AppSync Events Library (#3046)
1 parent efef6b1 commit 038707a

File tree

100 files changed

+42324
-6
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

100 files changed

+42324
-6
lines changed

.github/workflows/release_pr.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ on:
99
options:
1010
- AmplifyAndroid
1111
- ApolloExtensions
12+
- AppSyncEvents
1213
release_tag:
1314
description: 'Previous Release Tag'
1415
required: false

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,8 @@ __pycache__/
9898
#amplify
9999
.amplify/
100100
amplify/
101+
#keep amplify gen2 backend projects
102+
!**/androidTest/backend/amplify/
101103
build/
102104
dist/
103105
node_modules/

appsync/CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# Release 1.0.0
2+
3+
Initial Release

appsync/README.md

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
<img src="https://s3.amazonaws.com/aws-mobile-hub-images/aws-amplify-logo.png" alt="AWS Amplify" width="225">
2+
3+
---
4+
5+
# AWS AppSync Events for Android
6+
7+
These libraries allow you to connect to [AWS AppSync Events](https://docs.aws.amazon.com/appsync/latest/eventapi/event-api-welcome.html).
8+
AWS AppSync Events lets you create secure and performant serverless WebSocket APIs that can broadcast real-time event data to millions of subscribers, without you having to manage connections or resource scaling. With this feature, you can build multi-user features such as a collaborative document editors, chat apps, and live polling systems.
9+
10+
Learn more about AWS AppSync Events by visiting the [Developer Guide](https://docs.aws.amazon.com/appsync/latest/eventapi/event-api-welcome.html).
11+
12+
There are two libraries available:
13+
14+
- `aws-sdk-appsync-events`: This is a standalone library that allows developers to connect to AWS AppSync Events. It does not depend on Amplify, and instead leaves it to the application developer to supply tokens or signatures when using Owner or IAM-based authorization. This is the recommended library if your application does not already use Amplify.
15+
- `aws-sdk-appsync-amplify`: This library depends on `Amplify Android`, and contains some glue classes to use Amplify to implement the authorizers for `aws-sdk-appsync-events`. This additional library is recommended if your application is already using Amplify, and you want to authorize calls with AWS Cognito User Pool tokens or IAM.
16+
17+
## Installation
18+
19+
Add the dependency you prefer to your `build.gradle.kts` file.
20+
21+
```kotlin
22+
// Standalone AWS AppSync Events library that does not require Amplify
23+
implementation("com.amazonaws:aws-sdk-appsync-events:1.0.0")
24+
25+
// Allows Amplify to Authorize Events calls through UserPool tokens or IAM
26+
implementation("com.amazonaws:aws-sdk-appsync-amplify:1.0.0")
27+
```
28+
29+
## Usage Guide
30+
31+
See [AWS AppSync Events for Android Documentation](https://docs.amplify.aws/android/build-a-backend/data/connect-event-api/) for a complete implementation guide.
32+
33+
## Contributing
34+
35+
- [CONTRIBUTING.md](../CONTRIBUTING.md)
36+
37+
## Security
38+
39+
See [CONTRIBUTING](../CONTRIBUTING.md#security-issue-notifications) for more information.
40+
41+
## License
42+
43+
This project is licensed under the Apache-2.0 License.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
/build
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
public final class com/amazonaws/sdk/appsync/amplify/BuildConfig {
2+
public static final field BUILD_TYPE Ljava/lang/String;
3+
public static final field DEBUG Z
4+
public static final field LIBRARY_PACKAGE_NAME Ljava/lang/String;
5+
public static final field VERSION_NAME Ljava/lang/String;
6+
public fun <init> ()V
7+
}
8+
9+
public final class com/amazonaws/sdk/appsync/amplify/authorizers/AmplifyIamAuthorizer : com/amazonaws/sdk/appsync/core/AppSyncAuthorizer {
10+
public fun <init> (Ljava/lang/String;)V
11+
public fun getAuthorizationHeaders (Lcom/amazonaws/sdk/appsync/core/AppSyncRequest;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
12+
}
13+
14+
public final class com/amazonaws/sdk/appsync/amplify/authorizers/AmplifyUserPoolAuthorizer : com/amazonaws/sdk/appsync/core/AppSyncAuthorizer {
15+
public fun <init> ()V
16+
public fun getAuthorizationHeaders (Lcom/amazonaws/sdk/appsync/core/AppSyncRequest;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
17+
}
18+
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/*
2+
* Copyright 2025 Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License").
5+
* You may not use this file except in compliance with the License.
6+
* A copy of the License is located at
7+
*
8+
* http://aws.amazon.com/apache2.0
9+
*
10+
* or in the "license" file accompanying this file. This file is distributed
11+
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
12+
* express or implied. See the License for the specific language governing
13+
* permissions and limitations under the License.
14+
*/
15+
16+
import java.util.Properties
17+
18+
plugins {
19+
id("com.android.library")
20+
id("kotlin-android")
21+
}
22+
23+
apply(from = rootProject.file("configuration/publishing.gradle"))
24+
25+
fun readVersion() = Properties().run {
26+
file("../version.properties").inputStream().use { load(it) }
27+
get("VERSION_NAME").toString()
28+
}
29+
30+
project.setProperty("VERSION_NAME", readVersion())
31+
group = properties["POM_GROUP"].toString()
32+
33+
android {
34+
namespace = "com.amazonaws.sdk.appsync.amplify"
35+
}
36+
37+
dependencies {
38+
39+
api(project(":aws-sdk-appsync-core"))
40+
api(project(":core"))
41+
42+
implementation(project(":aws-auth-cognito"))
43+
implementation(project(":aws-core"))
44+
implementation(libs.aws.signing)
45+
46+
testImplementation(libs.test.junit)
47+
testImplementation(libs.test.mockk)
48+
testImplementation(libs.test.kotlin.coroutines)
49+
testImplementation(libs.test.kotest.assertions)
50+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
POM_GROUP=com.amazonaws
2+
POM_ARTIFACT_ID=aws-sdk-appsync-amplify
3+
POM_NAME=Amplify Extensions for AWS AppSync
4+
POM_DESCRIPTION=Amplify Extensions for AWS AppSync
5+
POM_PACKAGING=aar
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/*
2+
* Copyright 2025 Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License").
5+
* You may not use this file except in compliance with the License.
6+
* A copy of the License is located at
7+
*
8+
* http://aws.amazon.com/apache2.0
9+
*
10+
* or in the "license" file accompanying this file. This file is distributed
11+
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
12+
* express or implied. See the License for the specific language governing
13+
* permissions and limitations under the License.
14+
*/
15+
package com.amazonaws.sdk.appsync.amplify.authorizers
16+
17+
import com.amazonaws.sdk.appsync.amplify.util.AppSyncRequestSigner
18+
import com.amazonaws.sdk.appsync.core.AppSyncAuthorizer
19+
import com.amazonaws.sdk.appsync.core.AppSyncRequest
20+
import com.amazonaws.sdk.appsync.core.authorizers.IamAuthorizer
21+
import org.jetbrains.annotations.VisibleForTesting
22+
23+
/**
24+
* Authorizer implementation that provides IAM signing through Amplify & AWS Kotlin SDK (Smithy).
25+
*/
26+
class AmplifyIamAuthorizer @VisibleForTesting internal constructor(
27+
private val region: String,
28+
private val requestSigner: AppSyncRequestSigner
29+
) : AppSyncAuthorizer {
30+
31+
constructor(region: String) : this(region, requestSigner = AppSyncRequestSigner())
32+
33+
private val iamAuthorizer = IamAuthorizer { requestSigner.signAppSyncRequest(it, region) }
34+
35+
override suspend fun getAuthorizationHeaders(request: AppSyncRequest) =
36+
iamAuthorizer.getAuthorizationHeaders(request)
37+
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/*
2+
* Copyright 2025 Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License").
5+
* You may not use this file except in compliance with the License.
6+
* A copy of the License is located at
7+
*
8+
* http://aws.amazon.com/apache2.0
9+
*
10+
* or in the "license" file accompanying this file. This file is distributed
11+
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
12+
* express or implied. See the License for the specific language governing
13+
* permissions and limitations under the License.
14+
*/
15+
package com.amazonaws.sdk.appsync.amplify.authorizers
16+
17+
import com.amazonaws.sdk.appsync.core.AppSyncAuthorizer
18+
import com.amazonaws.sdk.appsync.core.AppSyncRequest
19+
import com.amazonaws.sdk.appsync.core.authorizers.AuthTokenAuthorizer
20+
import com.amplifyframework.auth.AuthCredentialsProvider
21+
import com.amplifyframework.auth.CognitoCredentialsProvider
22+
import kotlin.coroutines.resume
23+
import kotlin.coroutines.resumeWithException
24+
import kotlin.coroutines.suspendCoroutine
25+
import org.jetbrains.annotations.VisibleForTesting
26+
27+
/**
28+
* Authorizer implementation that provides Cognito User Pool tokens via Amplify Auth.
29+
*/
30+
class AmplifyUserPoolAuthorizer @VisibleForTesting internal constructor(
31+
private val accessTokenProvider: AccessTokenProvider
32+
) : AppSyncAuthorizer {
33+
34+
constructor() : this(accessTokenProvider = AccessTokenProvider())
35+
36+
private val authTokenAuthorizer = AuthTokenAuthorizer(
37+
fetchLatestAuthToken = accessTokenProvider::fetchLatestCognitoAuthToken
38+
)
39+
40+
override suspend fun getAuthorizationHeaders(request: AppSyncRequest) =
41+
authTokenAuthorizer.getAuthorizationHeaders(request)
42+
}
43+
44+
internal class AccessTokenProvider(
45+
private val credentialsProvider: AuthCredentialsProvider = CognitoCredentialsProvider()
46+
) {
47+
suspend fun fetchLatestCognitoAuthToken() = credentialsProvider.getAccessToken()
48+
49+
private suspend fun AuthCredentialsProvider.getAccessToken() = suspendCoroutine { continuation ->
50+
getAccessToken(
51+
{ token -> continuation.resume(token) },
52+
{ error -> continuation.resumeWithException(error) }
53+
)
54+
}
55+
}

0 commit comments

Comments
 (0)