Skip to content

Commit dc51c9f

Browse files
committed
feat(data): appsync apollo extensions
1 parent 9183a63 commit dc51c9f

File tree

1 file changed

+294
-0
lines changed
  • src/pages/[platform]/build-a-backend/data/aws-appsync-apollo-extensions

1 file changed

+294
-0
lines changed
Lines changed: 294 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,294 @@
1+
import { getCustomStaticPath } from '@/utils/getCustomStaticPath';
2+
3+
export const meta = {
4+
title: 'AWS AppSync Apollo Extensions',
5+
description:
6+
'AWS AppSync Apollo Extensions',
7+
platforms: [
8+
'android',
9+
'angular',
10+
'flutter',
11+
'javascript',
12+
'nextjs',
13+
'react',
14+
'react-native',
15+
'swift',
16+
'vue'
17+
]
18+
};
19+
20+
export function getStaticPaths() {
21+
return getCustomStaticPath(meta.platforms);
22+
}
23+
24+
export function getStaticProps(context) {
25+
return {
26+
props: {
27+
platform: context.params.platform,
28+
meta
29+
}
30+
};
31+
}
32+
33+
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.
34+
35+
<InlineFilter filters={["swift"]}>
36+
37+
To learn more about Apollo, see https://www.apollographql.com/docs/ios/.
38+
39+
</InlineFilter>
40+
41+
42+
<InlineFilter filters={["android"]}>
43+
44+
To learn more about Apollo, see https://www.apollographql.com/docs/kotlin.
45+
46+
</InlineFilter>
47+
48+
### Features
49+
50+
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.
51+
52+
The Amplify library provides components to facilitate configuring the authorizers with Apollo client by providing configuration values to connect to your Amplify Data backend.
53+
54+
<InlineFilter filters={["swift"]}>
55+
56+
### Install the AWS AppSync Apollo library
57+
58+
Add AWS AppSync Apollo Extensions into your project using Swift Package Manager.
59+
60+
Enter its GitHub URL (`https://github.com/aws-amplify/aws-appsync-apollo-extensions-swift`), select **Up to Next Major Version** and click **Add Package**
61+
62+
* Select the following libraries:
63+
* **AWSAppSyncApolloExtensions**
64+
65+
</InlineFilter>
66+
67+
### Connecting to AWS AppSync with Apollo client
68+
69+
AWS AppSync supports the following authorization modes (https://docs.aws.amazon.com/appsync/latest/devguide/security-authz.html)
70+
71+
#### API_KEY
72+
73+
<InlineFilter filters={["swift"]}>
74+
75+
```swift
76+
import AWSAppSyncApolloExtensions
77+
78+
let authorizer = APIKeyAuthorizer(apiKey: "[API_KEY]")
79+
let interceptor = AppSyncInterceptor(authorizer)
80+
```
81+
82+
</InlineFilter>
83+
84+
<InlineFilter filters={["android"]}>
85+
86+
```kotlin
87+
val authorizer = ApiKeyAuthorizer("[API_KEY]")
88+
val interceptor = AppSyncInterceptor(authorizer)
89+
```
90+
91+
</InlineFilter>
92+
93+
#### AMAZON_COGNITO_USER_POOLS
94+
95+
<InlineFilter filters={["swift"]}>
96+
97+
If you are using Amplify Auth, you can create a method that retrieves the Cognito access token
98+
99+
```swift
100+
import Amplify
101+
102+
func getUserPoolAccessToken() async throws -> String {
103+
let authSession = try await Amplify.Auth.fetchAuthSession()
104+
if let result = (authSession as? AuthCognitoTokensProvider)?.getCognitoTokens() {
105+
switch result {
106+
case .success(let tokens):
107+
return tokens.accessToken
108+
case .failure(let error):
109+
throw error
110+
}
111+
}
112+
throw AuthError.unknown("Did not receive a valid response from fetchAuthSession for get token.")
113+
}
114+
```
115+
116+
Then create the AuthTokenAuthorizer with this method.
117+
118+
```swift
119+
import AWSAppSyncApolloExtensions
120+
121+
let authorizer = AuthTokenAuthorizer(fetchLatestAuthToken: getUserPoolAccessToken)
122+
let interceptor = AppSyncInterceptor(authorizer)
123+
```
124+
</InlineFilter>
125+
126+
<InlineFilter filters={["android"]}>
127+
128+
Create the AuthTokenAuthorizer with this method.
129+
130+
```kotlin
131+
let authorizer = AuthTokenAuthorizer(fetchLatestAuthToken: getLatestTokenFromAmplify)
132+
```
133+
134+
</InlineFilter>
135+
136+
You can provide your own custom `fetchLatestAuthToken` provider for **AWS_LAMBDA** and **OPENID_CONNECT** auth modes.
137+
138+
#### AWS_IAM
139+
140+
<InlineFilter filters={["swift"]}>
141+
142+
If you are using Amplify Auth, you can use the following method for AWS_IAM auth
143+
144+
```
145+
import AWSCognitoAuthPlugin
146+
import AWSAppSyncApolloExtensions
147+
148+
let authorizer = IAMAuthorizer(
149+
signRequest: AWSCognitoAuthPlugin.createAppSyncSigner(
150+
region: "[REGION]"))
151+
```
152+
153+
</InlineFilter>
154+
155+
<InlineFilter filters={["android"]}>
156+
157+
If you are using Amplify Auth, you can use the following method for AWS_IAM auth
158+
159+
```
160+
val authorizer = IamAuthorizer { ApolloAmplifyConnector.signAppSyncRequest(it, "us-east-1") }
161+
```
162+
163+
</InlineFilter>
164+
165+
### Connecting Amplify Data to Apollo client
166+
167+
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/).
168+
169+
Once you have deployed your backend and created the `amplify_outputs.json`, you can use Amplify library to read and retrieve your configuration values with the following steps:
170+
171+
<InlineFilter filters={["swift"]}>
172+
173+
1. Enter its GitHub URL (`https://github.com/aws-amplify/amplify-swift`), select **Up to Next Major Version** and click **Add Package**
174+
2. Select the following libraries:
175+
1. **AWSPluginsCore**
176+
3. Drag and drop the `amplify_outputs.json` file into your Xcode project.
177+
4. Initialize the configuration with `try AWSAppSyncConfiguration(with: .amplifyOutputs)`
178+
179+
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.
180+
181+
```swift
182+
import Apollo
183+
import ApolloAPI
184+
import AWSPluginsCore
185+
import AWSAppSyncApolloExtensions
186+
187+
func createApolloClient() throws -> ApolloClient {
188+
let store = ApolloStore(cache: InMemoryNormalizedCache())
189+
190+
// 1. Read AWS AppSync API configuration from `amplify_outputs.json`
191+
let configuration = try AWSAppSyncConfiguration(with: .amplifyOutputs)
192+
193+
// 2. Use `configuration.apiKey` with APIKeyAuthorizer
194+
let authorizer = APIKeyAuthorizer(apiKey: configuration.apiKey ?? "")
195+
let interceptor = AppSyncInterceptor(authorizer)
196+
let interceptorProvider = DefaultPrependInterceptorProvider(interceptor: interceptor,
197+
store: store)
198+
// 3. Use `configuration.endpoint` with RequestChainNetworkTransport
199+
let transport = RequestChainNetworkTransport(interceptorProvider: interceptorProvider,
200+
endpointURL: configuration.endpoint)
201+
202+
return ApolloClient(networkTransport: transport, store: store)
203+
}
204+
```
205+
206+
</InlineFilter>
207+
208+
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).
209+
210+
211+
Some common ones are
212+
213+
* `publicAPIkey` strategy, `apiKey` authMode, **APIKeyAuthorizer**
214+
* `guest` strategy, `identityPool` authMode, **IAMAuthorizer**
215+
* `owner` strategy, `userPool` authMode, **AuthTokenAuthorizer**
216+
217+
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.
218+
219+
### Downloading the AWS AppSync schema
220+
221+
The schema is used by Apollo’s code generation tool to generate API code that helps you execute GraphQL operations. To retrieve your AWS AppSync schema:
222+
223+
<InlineFilter filters={["swift"]}>
224+
1. Navigate to your API on the AWS AppSync console
225+
2. On the left side, select Schema
226+
3. When viewing your schema, there should a “Export schema” drop down. Select this and download the `schema.json` file.
227+
4. Add this file to your project as directed by [Apollo Code Generation documentation](https://www.apollographql.com/docs/ios/code-generation/introduction)
228+
</InlineFilter>
229+
230+
<InlineFilter filters={["android"]}>
231+
1. Navigate to your API on the AWS AppSync console
232+
2. On the left side, select Schema
233+
3. When viewing your schema, there should a “Export schema” drop down. Select this and download the `schema.json` file.
234+
4. Add this file to your project as directed by [Apollo Code Generation documentation](https://www.apollographql.com/docs/ios/code-generation/introduction)
235+
</InlineFilter>
236+
237+
## Connecting to AWS AppSync real-time endpoint
238+
239+
The following example shows how you can create an Apollo client that allows performing GraphQL subscription operations with AWS AppSync.
240+
241+
<InlineFilter filters={["swift"]}>
242+
243+
```
244+
import Apollo
245+
import ApolloAPI
246+
import ApolloWebSocket
247+
import AWSPluginsCore
248+
import AWSAppSyncApolloExtensions
249+
250+
func createApolloClient() throws -> ApolloClient {
251+
let store = ApolloStore(cache: InMemoryNormalizedCache())
252+
let configuration = try AWSAppSyncConfiguration(with: .amplifyOutputs)
253+
254+
// 1. Create your authorizer
255+
let authorizer = /* your Authorizer */
256+
let interceptor = AppSyncInterceptor(authorizer)
257+
258+
let interceptorProvider = DefaultPrependInterceptorProvider(interceptor: interceptor,
259+
store: store)
260+
let transport = RequestChainNetworkTransport(interceptorProvider: interceptorProvider,
261+
endpointURL: configuration.endpoint)
262+
263+
// 2. Create the AWS AppSync compatible websocket client
264+
let websocket = AppSyncWebSocketClient(endpointURL: configuration.endpoint,
265+
authorizer: authorizer)
266+
// 3. Add it to the WebSocketTransport
267+
let webSocketTransport = WebSocketTransport(websocket: websocket)
268+
// 4. Create a SplitNetworkTransport
269+
let splitTransport = SplitNetworkTransport(
270+
uploadingNetworkTransport: transport,
271+
webSocketNetworkTransport: webSocketTransport
272+
)
273+
// 5. Pass the SplitNetworkTransport to the ApolloClient
274+
return ApolloClient(networkTransport: splitTransport, store: store)
275+
}
276+
```
277+
278+
</InlineFilter>
279+
280+
<InlineFilter filters={["android"]}>
281+
282+
```kotlin
283+
// Create the network transport
284+
val networkTransport = WebSocketNetworkTransport.Builder()
285+
.protocol(AppSyncProtocol.Factory(endpoint, authorizer))
286+
.build()
287+
288+
// Use the network transport when creating the Apollo Client
289+
val apolloClient = ApolloClient.Builder()
290+
.subscriptionNetworkTransport(networkTransport)
291+
.build()
292+
```
293+
294+
</InlineFilter>

0 commit comments

Comments
 (0)