-
Notifications
You must be signed in to change notification settings - Fork 1.1k
feat(data): appsync apollo extensions #7930
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
Changes from 10 commits
dc51c9f
14d3be9
48829bd
b0ab456
18b7017
b838517
97e6cef
43233dd
29de8ee
ca27228
80441bd
c53427f
f00d9ae
209e397
68c8632
0ccaeac
3b37722
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -0,0 +1,321 @@ | ||||||
import { getCustomStaticPath } from '@/utils/getCustomStaticPath'; | ||||||
|
||||||
export const meta = { | ||||||
title: 'AWS AppSync Apollo Extensions', | ||||||
description: | ||||||
'AWS AppSync Apollo Extensions', | ||||||
platforms: [ | ||||||
'android', | ||||||
'swift', | ||||||
] | ||||||
}; | ||||||
|
||||||
export function getStaticPaths() { | ||||||
return getCustomStaticPath(meta.platforms); | ||||||
} | ||||||
|
||||||
export function getStaticProps(context) { | ||||||
return { | ||||||
props: { | ||||||
platform: context.params.platform, | ||||||
meta | ||||||
} | ||||||
}; | ||||||
} | ||||||
|
||||||
AWS AppSync Apollo Extensions provides a seamless way to connect to your AWS AppSync while using the Apollo client. Apollo client is an open-source GraphQL client. | ||||||
|
||||||
<InlineFilter filters={["swift"]}> | ||||||
|
||||||
To learn more about Apollo, see https://www.apollographql.com/docs/ios/. | ||||||
|
||||||
</InlineFilter> | ||||||
|
||||||
|
||||||
<InlineFilter filters={["android"]}> | ||||||
|
||||||
To learn more about Apollo, see https://www.apollographql.com/docs/kotlin. | ||||||
|
||||||
</InlineFilter> | ||||||
|
||||||
### Features | ||||||
|
||||||
AWS AppSync Apollo Extensions provide AWS AppSync authorizers to be used with the Apollo client to make it simple to configure runtime interceptors and apply the correct authorization payloads to your GraphQL operations. | ||||||
|
||||||
The Amplify library provides components to facilitate configuring the authorizers with Apollo client by providing configuration values to connect to your Amplify Data backend. | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
|
||||||
<InlineFilter filters={["android"]}> | ||||||
|
||||||
### Install the AWS AppSync Apollo library | ||||||
|
||||||
Add AWS AppSync Apollo Extensions dependency to your app/build.gradle.kts file: | ||||||
lawmicha marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||||||
|
||||||
```kotlin title="app/build.gradle.kts" | ||||||
dependencies { | ||||||
// highlight-start | ||||||
implementation("com.amplifyframework:apollo-appsync:1.0.0") | ||||||
// highlight-end | ||||||
} | ||||||
``` | ||||||
|
||||||
</InlineFilter> | ||||||
|
||||||
<InlineFilter filters={["swift"]}> | ||||||
mattcreaser marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||||||
|
||||||
### Install the AWS AppSync Apollo library | ||||||
|
||||||
Add AWS AppSync Apollo Extensions into your project using Swift Package Manager. | ||||||
|
||||||
Enter its GitHub URL (`https://github.com/aws-amplify/aws-appsync-apollo-extensions-swift`), select **Up to Next Major Version** and click **Add Package** | ||||||
|
||||||
* Select the following libraries: | ||||||
* **AWSAppSyncApolloExtensions** | ||||||
|
||||||
</InlineFilter> | ||||||
|
||||||
### Connecting to AWS AppSync with Apollo client | ||||||
|
||||||
AWS AppSync supports the following [authorization modes](https://docs.aws.amazon.com/appsync/latest/devguide/security-authz.html) | ||||||
|
||||||
#### API_KEY | ||||||
|
||||||
<InlineFilter filters={["swift"]}> | ||||||
|
||||||
```swift | ||||||
import AWSAppSyncApolloExtensions | ||||||
|
||||||
let authorizer = APIKeyAuthorizer(apiKey: "[API_KEY]") | ||||||
let interceptor = AppSyncInterceptor(authorizer) | ||||||
``` | ||||||
|
||||||
</InlineFilter> | ||||||
|
||||||
<InlineFilter filters={["android"]}> | ||||||
|
||||||
```kotlin | ||||||
val authorizer = ApiKeyAuthorizer("[API_KEY]") | ||||||
val interceptor = AppSyncInterceptor(authorizer) | ||||||
``` | ||||||
|
||||||
</InlineFilter> | ||||||
|
||||||
#### AMAZON_COGNITO_USER_POOLS | ||||||
|
||||||
<InlineFilter filters={["swift"]}> | ||||||
|
||||||
If you are using Amplify Auth, you can create a method that retrieves the Cognito access token | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Amplify auth There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||||||
|
||||||
```swift | ||||||
import Amplify | ||||||
|
||||||
func getUserPoolAccessToken() async throws -> String { | ||||||
let authSession = try await Amplify.Auth.fetchAuthSession() | ||||||
if let result = (authSession as? AuthCognitoTokensProvider)?.getCognitoTokens() { | ||||||
switch result { | ||||||
case .success(let tokens): | ||||||
return tokens.accessToken | ||||||
case .failure(let error): | ||||||
throw error | ||||||
} | ||||||
} | ||||||
throw AuthError.unknown("Did not receive a valid response from fetchAuthSession for get token.") | ||||||
} | ||||||
``` | ||||||
|
||||||
Then create the AuthTokenAuthorizer with this method. | ||||||
|
||||||
```swift | ||||||
import AWSAppSyncApolloExtensions | ||||||
|
||||||
let authorizer = AuthTokenAuthorizer(fetchLatestAuthToken: getUserPoolAccessToken) | ||||||
let interceptor = AppSyncInterceptor(authorizer) | ||||||
``` | ||||||
</InlineFilter> | ||||||
|
||||||
<InlineFilter filters={["android"]}> | ||||||
|
||||||
Create the AuthTokenAuthorizer with this method. | ||||||
|
||||||
```kotlin | ||||||
val authorizer = AuthTokenAuthorizer { ApolloAmplifyConnector.fetchLatestCognitoAuthToken() } | ||||||
``` | ||||||
|
||||||
</InlineFilter> | ||||||
|
||||||
You can provide your own custom `fetchLatestAuthToken` provider for **AWS_LAMBDA** and **OPENID_CONNECT** auth modes. | ||||||
|
||||||
#### AWS_IAM | ||||||
|
||||||
<InlineFilter filters={["swift"]}> | ||||||
|
||||||
If you are using Amplify Auth, you can use the following method for AWS_IAM auth | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Amplify auth |
||||||
|
||||||
```swift | ||||||
import AWSCognitoAuthPlugin | ||||||
import AWSAppSyncApolloExtensions | ||||||
|
||||||
let authorizer = IAMAuthorizer( | ||||||
signRequest: AWSCognitoAuthPlugin.createAppSyncSigner( | ||||||
region: "[REGION]")) | ||||||
``` | ||||||
|
||||||
</InlineFilter> | ||||||
|
||||||
<InlineFilter filters={["android"]}> | ||||||
|
||||||
If you are using Amplify Auth, you can use the following method for AWS_IAM auth | ||||||
|
||||||
```kotlin | ||||||
val authorizer = IamAuthorizer { ApolloAmplifyConnector.signAppSyncRequest(it, "us-east-1") } | ||||||
``` | ||||||
|
||||||
</InlineFilter> | ||||||
|
||||||
### Connecting Amplify Data to Apollo client | ||||||
|
||||||
Before you begin, you will need an Amplify Data backend deploy. To get started, see [Set up Data](/[platform]/swift/build-a-backend/data/set-up-data/). | ||||||
|
||||||
Once you have deployed your backend and created the `amplify_outputs.json` file, you can use Amplify library to read and retrieve your configuration values with the following steps: | ||||||
|
||||||
<InlineFilter filters={["swift"]}> | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Need Android version of this section There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Added the Android section, which is
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Updated dependency name There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Updated code snippet There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. missing the |
||||||
|
||||||
1. Enter its GitHub URL (`https://github.com/aws-amplify/amplify-swift`), select **Up to Next Major Version** and click **Add Package** | ||||||
2. Select the following libraries: | ||||||
1. **AWSPluginsCore** | ||||||
3. Drag and drop the `amplify_outputs.json` file into your Xcode project. | ||||||
4. Initialize the configuration with `try AWSAppSyncConfiguration(with: .amplifyOutputs)` | ||||||
|
||||||
The resulting configuration object will have the `endpoint`, `region`, and optional `apiKey.` The following example shows reading the `amplify_outputs.json` file from the main bundle to instantiate the configuration and uses it to configure the Apollo client for **API_Key** authorization. | ||||||
|
||||||
```swift | ||||||
import Apollo | ||||||
import ApolloAPI | ||||||
import AWSPluginsCore | ||||||
import AWSAppSyncApolloExtensions | ||||||
|
||||||
func createApolloClient() throws -> ApolloClient { | ||||||
let store = ApolloStore(cache: InMemoryNormalizedCache()) | ||||||
|
||||||
// 1. Read AWS AppSync API configuration from `amplify_outputs.json` | ||||||
let configuration = try AWSAppSyncConfiguration(with: .amplifyOutputs) | ||||||
|
||||||
// 2. Use `configuration.apiKey` with APIKeyAuthorizer | ||||||
let authorizer = APIKeyAuthorizer(apiKey: configuration.apiKey ?? "") | ||||||
let interceptor = AppSyncInterceptor(authorizer) | ||||||
let interceptorProvider = DefaultPrependInterceptorProvider(interceptor: interceptor, | ||||||
store: store) | ||||||
// 3. Use `configuration.endpoint` with RequestChainNetworkTransport | ||||||
let transport = RequestChainNetworkTransport(interceptorProvider: interceptorProvider, | ||||||
endpointURL: configuration.endpoint) | ||||||
|
||||||
return ApolloClient(networkTransport: transport, store: store) | ||||||
} | ||||||
``` | ||||||
|
||||||
</InlineFilter> | ||||||
|
||||||
<InlineFilter filters={["android"]}> | ||||||
|
||||||
Add `apollo-appsync-amplify` dependency to your app/build.gradle.kts file: | ||||||
|
||||||
```kotlin title="app/build.gradle.kts" | ||||||
dependencies { | ||||||
// highlight-start | ||||||
implementation("com.amplifyframework:apollo-appsync-amplify:1.0.0") | ||||||
// highlight-end | ||||||
} | ||||||
``` | ||||||
|
||||||
```kotlin | ||||||
Code Sample | ||||||
lawmicha marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||||||
``` | ||||||
|
||||||
</InlineFilter> | ||||||
|
||||||
Depending on your authorization strategy defined on your schema, you can use the corresponding Authorizer. To read more about the strategies and their corresponding auth modes, see [Available authorization strategies](/[platform]/build-a-backend/data/customize-authz/#available-authorization-strategies). | ||||||
|
||||||
|
||||||
Some common ones are | ||||||
|
||||||
* `publicAPIkey` strategy, `apiKey` authMode, **APIKeyAuthorizer** | ||||||
* `guest` strategy, `identityPool` authMode, **IAMAuthorizer** | ||||||
* `owner` strategy, `userPool` authMode, **AuthTokenAuthorizer** | ||||||
|
||||||
If you define multiple authorization strategies on a single model, you will have to create separate Apollo client instances for each Authorizer that you want to use in your app. | ||||||
|
||||||
### Downloading the AWS AppSync schema | ||||||
|
||||||
The schema is used by Apollo’s code generation tool to generate API code that helps you execute GraphQL operations. The following steps integrate your AppSync schema with Apollo's code generation process: | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. AppSync is prefix required - always need AWS before it (AWS AppSync) |
||||||
|
||||||
<InlineFilter filters={["swift"]}> | ||||||
1. Navigate to your API on the [AWS AppSync console](https://console.aws.amazon.com/appsync/home) | ||||||
2. On the left side, select Schema | ||||||
3. When viewing your schema, there should a “Export schema” drop down. Select this and download the `schema.json` file. | ||||||
4. Add this file to your project as directed by [Apollo Code Generation documentation](https://www.apollographql.com/docs/ios/code-generation/introduction) | ||||||
|
||||||
You can alternatively download the introspection schema using the [`fetch-schema`](https://www.apollographql.com/docs/ios/code-generation/codegen-cli#fetch-schema) command with the `amplify-ios-cli` tool. | ||||||
|
||||||
</InlineFilter> | ||||||
|
||||||
<InlineFilter filters={["android"]}> | ||||||
1. Navigate to your API on the [AWS AppSync console](https://console.aws.amazon.com/appsync/home) | ||||||
2. On the left side, select Schema | ||||||
3. When viewing your schema, there should a “Export schema” drop down. Select this and download the `schema.json` file. | ||||||
4. Add this file to your project as directed by [Apollo documentation](https://www.apollographql.com/docs/kotlin/advanced/plugin-recipes#specifying-the-schema-location) | ||||||
</InlineFilter> | ||||||
|
||||||
## Connecting to AWS AppSync real-time endpoint | ||||||
|
||||||
The following example shows how you can create an Apollo client that allows performing GraphQL subscription operations with AWS AppSync. | ||||||
|
||||||
<InlineFilter filters={["swift"]}> | ||||||
|
||||||
```swift | ||||||
import Apollo | ||||||
import ApolloAPI | ||||||
import ApolloWebSocket | ||||||
import AWSPluginsCore | ||||||
import AWSAppSyncApolloExtensions | ||||||
|
||||||
func createApolloClient() throws -> ApolloClient { | ||||||
let store = ApolloStore(cache: InMemoryNormalizedCache()) | ||||||
let configuration = try AWSAppSyncConfiguration(with: .amplifyOutputs) | ||||||
|
||||||
// 1. Create your authorizer | ||||||
let authorizer = /* your Authorizer */ | ||||||
let interceptor = AppSyncInterceptor(authorizer) | ||||||
|
||||||
let interceptorProvider = DefaultPrependInterceptorProvider(interceptor: interceptor, | ||||||
store: store) | ||||||
let transport = RequestChainNetworkTransport(interceptorProvider: interceptorProvider, | ||||||
endpointURL: configuration.endpoint) | ||||||
|
||||||
// 2. Create the AWS AppSync compatible websocket client | ||||||
let websocket = AppSyncWebSocketClient(endpointURL: configuration.endpoint, | ||||||
authorizer: authorizer) | ||||||
// 3. Add it to the WebSocketTransport | ||||||
let webSocketTransport = WebSocketTransport(websocket: websocket) | ||||||
// 4. Create a SplitNetworkTransport | ||||||
let splitTransport = SplitNetworkTransport( | ||||||
uploadingNetworkTransport: transport, | ||||||
webSocketNetworkTransport: webSocketTransport | ||||||
) | ||||||
// 5. Pass the SplitNetworkTransport to the ApolloClient | ||||||
return ApolloClient(networkTransport: splitTransport, store: store) | ||||||
} | ||||||
``` | ||||||
|
||||||
</InlineFilter> | ||||||
|
||||||
<InlineFilter filters={["android"]}> | ||||||
|
||||||
```kotlin | ||||||
val endpoint = AppSyncEndpoint("<your_appsync_endpoint>") | ||||||
val authorizer = /* your Authorizer */ | ||||||
|
||||||
val apolloClient = ApolloClient.Builder() | ||||||
.appSync(endpoint, authorizer) | ||||||
.build() | ||||||
``` | ||||||
|
||||||
</InlineFilter> |
Uh oh!
There was an error while loading. Please reload this page.