Using AWS as a Back End: Authentication & API
Learn how to use Amazon Web Services (AWS) to build a back end for your iOS apps with AWS Amplify and Cognito, using GraphQL. By Tom Elliott.
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Contents
Using AWS as a Back End: Authentication & API
35 mins
- Getting Started
- Introduction to the App
- Setting Up Your Environment
- AWS Amplify
- Installing and Configuring Amplify
- Adding Amplify to Your App
- Configuring AWS Cognito
- Adding Authentication With Amazon Cognito
- Completing the Authentication Service
- GraphQL, AppSync and DynamoDB
- Adding a GraphQL API
- Defining Your Schema
- Generating the Database
- Writing Data
- Reading and Writing AppSync Data From Swift
- Reading Data From AppSync
- Creating Data in DynamoDB
- Where to Go From Here?
Amazon Web Services (AWS) is a cloud computing platform. To support cloud computing, Amazon owns and operates data centers around the globe. It offers various infrastructure and software products “as a service”. For example, you can use Amazon EC2 to reserve virtual servers within Amazon’s data centers. Or you can use Amazon SageMaker to build and deploy machine learning models quickly and easily. AWS offers nearly 200 separate services, so whatever you need for your next project, you’re likely to find it!
As you work through the tutorial, you’ll learn how to use AWS Amplify to add authentication and database storage to a chat app called Isolation Nation.
This is an advanced-level tutorial. Before starting it, you should have a good understanding of Swift and SwiftUI. You should also have some understanding of both GraphQL and CocoaPods. If you need to brush up on any of these first, try the following tutorials:
Now it’s time to get cracking!
Getting Started
Isolation Nation is an app for people who are self-isolating due to COVID-19. It lets them request help from others in their local community. Isolation Nation works by asking the user for their postcode (the UK equivalent of a zip code) and adding it to a thread for their postcode area. For example, the full postcode for Buckingham Palace is SW1A 1AA. The postcode area is SW1A, and it represents the area shown here.
Users whose postcode is within the same area are added to a single thread. They can then send messages and replies to others in the same area.
Download the starter project by clicking the Download Materials button at the top or bottom of the tutorial. Open the workspace (not the project) for the IsolationNation starter project in Xcode.
Introduction to the App
Build and run the project. The app displays a list with a single-thread item, SW1A. Tap the item. The app will navigate to the message list for that location.
Tap any of the messages to see the list of replies for each message.
The app contains four main screens: Home, Threads, Messages and Replies. In Xcode, you can see a group for each screen in the Project navigator. You can also see a view model for each screen. These are outside their groups, so they’re easier to find.
Take a look around the project:
- AppDelegate sets a logged-in user.
-
SceneDelegate sets
RootView
as the root view of the SwiftUI view hierarchy. -
RootView checks for the existence of a signed-in user and, if one exists, loads
HomeScreen
. -
HomeScreen loads
ThreadsScreen
.
The Threads, Messages and Replies screens all have a similar structure. Each one uses its view model as an ObservedObject
to populate its view.
Open ThreadsScreenViewModel.swift. The view model contains a property, threadListState
, which publishes an array of ThreadModel
objects wrapped in a Loading
enum. After the initializers, perform(action:)
defines an API. This API allows a view to send a request to the view model to perform an action. The handlers for those actions follow.
On first inspection, the app may look like it’s already working. But notice how fetchThreads()
simply returns a hard-coded list. The aim of this tutorial is to build a fully functional back end and remove all the hard-coded data. :]
First, you need to sign up for an AWS account and install some software onto your computer.
Setting Up Your Environment
Open a browser and head over to the AWS Homepage.
If you already have an AWS account, sign in. Otherwise, click Create an AWS account in the top right corner, and sign up for the free tier. Once AWS creates your account, sign in as the Root user with the credentials you just created.
Now it’s time to install the software prerequisites. Open Terminal.
First, make sure you have Git installed. It’s pre-installed on every modern macOS, so it should be. In your terminal, type the following:
git --version
Make sure your version of Git is 2.14.1 or later. If not, you can install it here.
Next, check if you have Node v10 or later installed by running the following command in your terminal:
node --version
If you don’t have it installed, you can install it here.
And, finally, if you don’t have it already, install CocoaPods by running this command in your terminal:
sudo gem install cocoapods
Next, you’ll install and configure Amplify.
AWS Amplify
Amplify consists of three separate, but related, products:
- First, there’s a Command Line Interface (CLI) for programmatically creating and reserving AWS resources on behalf of your project. AWS is powerful, but also complex. Amplify makes it easy!
- Second, Amplify provides libraries for several popular programming environments, including iOS. These libraries provide simplified APIs for common app development use cases.
- Finally, Amplify provides a limited set of UI components for quickly building out common user flows such as authentication. These components are currently not available for iOS.
Installing and Configuring Amplify
To get started with Amplify, install the CLI by typing the following into your terminal:
npm install -g @aws-amplify/cli amplify-app
The -g
flag means the CLI will install globally on your computer, rather than just for a single project.
Once you’ve installed the CLI, you must configure it so that it links to your AWS Account. Run the following in your terminal:
amplify configure
The terminal screen will ask you to log in to your AWS account, and a new browser tab will open. As requested by the CLI, press Enter to continue. Press Enter to select the default AWS region and type a username for your Amplify IAM user:
Another browser tab will open automatically. Click Next: Permissions ▸ Next: Tags ▸ Next: Review ▸ Create user.
Click Close.
Back in the terminal, follow the instructions to add your access key ID and secret access key.
Finally, create a profile name:
Congratulations! Amplify is now set up on your computer. Next, you’ll add it to your app.
Adding Amplify to Your App
In Xcode, open Podfile. Between the # Pods for IsolationHelp
comment and the end
at the end of the file, add the following new dependencies:
pod 'Amplify' pod 'Amplify/Tools'
Next, in your terminal, navigate to the root of the project directory. Type the following to install the dependencies in your project:
pod install --repo-update
Amplify is the main dependency. It provides your app with access to all the Amplify APIs. Amplify Tools adds various automation to Xcode’s build process to make working with Amplify easier.
Next, click the IsolationNation project in the project workspace, then the IsolationNation target.
In the Build Phases tab, click the plus button to add another phase. Choose New Run Script Phase.
Name the phase Amplify Tools by clicking the Run script title. Click and drag it above the Compile Sources phase.
Update the shell script to the following:
"${PODS_ROOT}/AmplifyTools/amplify-tools.sh"
To ensure all of the Amplify CLI tools operate correctly, enter the following command in Terminal:
npm i --package-lock-only
Build your project. After the build completes, the Project navigator will have a new group called AmplifyConfig. This folder houses files containing configuration and resource identifiers for Amplify.
Next, in your terminal, type the following:
amplify init
Press Enter to accept the default project name, and select None as your default editor. When asked if you would like to use a profile, type Y and then choose the default profile.
This will take some time to complete, as the CLI creates AWS resources for you.
Next, type the following into your terminal:
amplify console
This will open the Amplify Console in your browser. If you get an error that your project doesn’t exist, make sure you’ve selected the N. Virginia region.
At this point, you may want to look around the console to become familiar with it. For now, though, there’s not much to see, since you haven’t added any services to your app yet.
However, you’re about to turn Isolation Nation into a bona fide app! The first step is to add support for users to create accounts and log in. Amazon provides a service for this called Cognito. Cognito has a User Pool, which serves as a directory of all your users. You can configure your User Pool to allow users to log in with username and password, social identity providers like Google or Facebook, or enterprise security systems like SAML.
Configuring AWS Cognito
To start, open Podfile in Xcode and add the following dependency after the two existing dependencies:
pod 'AmplifyPlugins/AWSCognitoAuthPlugin'
Next, install the dependency by running this command in your terminal:
pod install --repo-update
Finally, use the Amplify CLI to configure Cognito for your project. Type the following command into the terminal window at the root of your project:
amplify add auth
When the CLI prompts you, select Default configuration ▸ Username ▸ No, I am done (the default option in each case), and wait for the Amplify CLI to complete.
It’s important to note that the Amplify CLI has now configured Cognito for your project locally, but it has not saved that configuration in the cloud. You can confirm this by typing the following in the terminal:
amplify status
This tells you that you need to create a resource in the Auth category with the given name. Type the following into the terminal and confirm in the affirmative when asked:
amplify push
When you are asked if you would like to generate code for your new API, enter N.
This will likely take several minutes to complete as Amplify creates AWS resources for you.
Once it’s finished, head back to the Amplify Console in your browser. Select your app and then the Backend environments tab.
An Authentication category now appears in your back end.
Click the Authentication link. Then, in the Users section, click the View in Cognito button to view the Cognito User Pool.
Next, select App client settings in the left-hand menu. Copy the client ID and save it somewhere. You’ll need this later.
Phew! All your setup is now out of the way. Next, it’s time to add the code to your app to handle authentication.
Adding Authentication With Amazon Cognito
Open AppDelegate.swift. At the top of the file, after the UIKit import, add imports for Amplify:
import Amplify
import AmplifyPlugins
Remove the line that sets userSession.loggedInUser
to “Lizzie”.
Immediately after initializing authenticationService
, add the following:
do {
try Amplify.add(plugin: AWSCognitoAuthPlugin())
try Amplify.configure()
#if DEBUG
Amplify.Logging.logLevel = .debug
#else
Amplify.Logging.logLevel = .error
#endif
} catch {
print("Error initializing Amplify. \(error)")
}
This code configures the Amplify library with a Cognito authentication plug-in. Then it sets an appropriate log level for Amplify.
Build and run.
Oh no! Now the app displays a never-ending spinner! Clearly you’re not finished yet.
Completing the Authentication Service
Open AuthenticationService.swift. In the section identified by // MARK: Public API
, you’ll see stub functions with names like signIn(as:identifiedBy:)
and checkAuthSession()
. Now it’s time to write some code that uses your Cognito back end.
First, add a new import at the top of the file:
import Amplify
Next, locate the empty checkAuthSession()
and add the following implementation:
// 1
_ = Amplify.Auth.fetchAuthSession { [self] result in
switch result {
// 2
case .failure(let error):
logger.logError(error)
signOut()
// 3
case .success(let session):
if !session.isSignedIn {
setUserSessionData(nil)
return
}
// 4
guard let authUser = Amplify.Auth.getCurrentUser() else {
let authError = IsolationNationError.unexpctedAuthResponse
logger.logError(authError)
signOut()
return
}
setUserSessionData(authUser.username)
}
}
Here’s what this code does:
- Request the current auth session from Amplify.
- If there’s an error, sign the user out.
- On success, confirm the user is signed in.
- If the user is signed in, fetch the current user and set the details on the user session.
Build and run. The spinner is now replaced with a sign-in screen. :]
Next, add the sign-in code. Remove all the code inside signIn(as:identifiedBy:)
, and replace it with the following:
return Future { promise in
// 1
_ = Amplify.Auth
.signIn(username: username, password: password) { [self] result in
switch result {
// 2
case .failure(let error):
logger.logError(error.localizedDescription)
promise(.failure(error))
// 3
case .success:
guard let authUser = Amplify.Auth.getCurrentUser() else {
let authError = IsolationNationError.unexpctedAuthResponse
logger.logError(authError)
signOut()
promise(.failure(authError))
return
}
// 4
setUserSessionData(authUser.username)
}
}
}
This is what you’re doing:
- Call the Amplify sign-in API, passing the username and password.
- Check and handle failures.
- On success, fetch the current logged-in user.
- Set the user’s details on the user session, as before.
With this set up, users can sign in to your app!
But there’s just one problem: You don’t have any existing users, and there’s still no way to sign up. Time to fix that.
Replace the body of signUp(as:identifiedBy:with:)
with the following:
return Future { promise in
// 1
let userAttributes = [AuthUserAttribute(.email, value: email)]
let options = AuthSignUpRequest.Options(userAttributes: userAttributes)
// 2
_ = Amplify.Auth.signUp(
username: username,
password: password,
options: options
) { [self] result in
DispatchQueue.main.async {
switch result {
case .failure(let error):
logger.logError(error.localizedDescription)
promise(.failure(error))
case .success(let amplifyResult):
// 3
if case .confirmUser = amplifyResult.nextStep {
promise(.success(.awaitingConfirmation(username, password)))
} else {
let error = IsolationNationError.unexpctedAuthResponse
logger.logError(error.localizedDescription)
promise(.failure(error))
}
}
}
}
}
In this code, you do the following:
- Configure a sign-up request to expect sign-up via email.
- Perform the sign-up using Amplify. You handle the result as you did in the previous examples.
- If sign-up is a success, return the
awaitingConfirmation
state. Amplify will send the user a code via email to confirm ownership of the address provided.
Next, you need to allow users to confirm their email address. Replace the contents of confirmSignUp(for:with:confirmedBy:)
with this:
return Future { promise in
// 1
_ = Amplify.Auth.confirmSignUp(
for: username,
confirmationCode: confirmationCode
) { [self] result in
switch result {
case .failure(let error):
logger.logError(error.localizedDescription)
promise(.failure(error))
case .success:
// 2
_ = Amplify.Auth.signIn(
username: username,
password: password
) { result in
switch result {
case .failure(let error):
logger.logError(error.localizedDescription)
promise(.failure(error))
case .success:
// 3
checkAuthSession()
}
}
}
}
}
In this code, you verify the user:
- Confirm the sign-up with Amplify and handle the response in the usual fashion.
- On success, sign the user in.
- Call
checkAuthSession()
, which sets the user session.
Update signOut()
to sign the user out of Cognito and clear their user session. Add the following code after setting the user session to nil
:
_ = Amplify.Auth.signOut { [self] result in
switch result {
case .failure(let error):
logger.logError(error)
default:
break
}
}
Finally, open AppDelegate.swift. Add the following to the bottom of application(_:didFinishLaunchingWithOptions:)
, just before return true
:
// Listen to auth changes
_ = Amplify.Hub.listen(to: .auth) { payload in
switch payload.eventName {
case HubPayload.EventName.Auth.sessionExpired:
authenticationService.checkAuthSession()
default:
break
}
}
By default, the authentication token returned from Cognito expires after an hour. But you can extend it without asking the user to log in again. That’s what’s happening here.
Build and run. This time, tap the Sign Up button and sign up with a username, email address and password.
AWS will send a confirmation code in an email to the address you provided. When that arrives, enter it and tap Confirm.
Congratulations! You have successfully logged into the app. :] Now, sign out and sign back in using the same user to verify that your code is working.
Next, confirm that your user now appears in the cloud. In your browser, go to your earlier Cognito tab. Click the Users and groups option in the left-hand menu. Select your user from the list (of one user!).
Find the sub field and save it somewhere. You’ll need this later.
GraphQL, AppSync and DynamoDB
Providing login capability in your app is a good start. But most products also need a way for users to modify and save data. For many modern apps, this data needs to be accessible to other users. A common solution to this problem is to persist the data in a database stored on a server somewhere in the cloud.
AWS provides many different database services, each with its own benefits and trade-offs. In this tutorial, you’ll use the document database DynamoDB. With DynamoDB, you don’t have to define a schema up front. This feature lends itself to quick prototyping or iterating on new ideas for your app.
Many mobile apps use a common architectural pattern in which the business and security logic resides in a back-end server. The app communicates with the server via a network API like GraphQL or REST. The server saves, retrieves or updates records in a database.
AppSync is an AWS service that generates both the database and the back end automatically, using your GraphQL schema. You define your model objects in the GraphQL schema, and AppSync generates the code for the back end. It then deploys the services needed to run your back end. And it creates the DynamoDB tables required to save your data.
Adding a GraphQL API
Back in Xcode, open Podfile and add the following dependency:
pod 'AmplifyPlugins/AWSAPIPlugin'
AWSAPIPlugin
adds support to the Amplify Library for AppSync. Update your workspace by running the following from the command line:
pod install --repo-update
The first model object you’re going to add is a User
object. Normally, Cognito handles user data. But Cognito’s data is private to the individual. And, in the Isolation Nation app, users must be able to see data about each other, such as their username. So this app needs a User Model as well as the Cognito data.
Defining Your Schema
In Xcode, open schema.graphql in the AmplifyConfig group. Replace the contents with the following:
# 1 type User # 4 @model { # 2 id: ID! username: String! # 3 sub: String! postcode: String createdAt: AWSDateTime! }
Here’s what you’re doing:
- You declare a
User
type. - You define various fields for the user type as
code: Type
tuples. For example, theid
field is of typeID
, and thepostcode
field is of typeString
. The!
operator signifies that a type is required. - The
sub
field will contain thesub
record from Cognito. This is the unique identifier for the user. - You annotate the
user
type with the@model
directive.
If you’re familiar with GraphQL, most of this will look pretty straightforward. However, there are a few bits unique to AppSync.
AppSync uses directives to provide a declarative API that allows you to specify how you want AppSync to configure each type or field. In this example, you specify that your user type is a model
. This indicates to AppSync that it should create a DynamoDB table for this type.
When you added Amplify Tools as a dependency in your project earlier, Amplify created an API on your behalf. However, this was before you added authentication to the project. Your API doesn’t know anything about the Cognito User Pool you just created. Before you continue, you need to fix that.
Generating the Database
In your terminal, run the following command:
amplify api update
When prompted, select GraphQL ▸ Update auth settings ▸ Amazon Cognito User Pool, and then N.
Next, open amplifytools.xcconfig. Override the options by adding the code:
push=true modelgen=true profile=default envName=dev
Here, you’re instructing the Amplify Tools script to take these actions:
- Push changes to the cloud when it runs.
- Generate models in Swift for your
@model
types. - Use your default AWS profile and the dev environment you created earlier.
Build your project in Xcode. If you open the Report navigator, you’ll see that the Amplify Tools script is now generating Swift models on your behalf.
This build will take a long time! This is because the script is also running amplify push
to generate all the necessary resources in the cloud.
When the build is complete, open the Project navigator. Confirm that a new group has been added to your project, and that it contains generated model files for your User
model.
In your browser, go back to the Amplify Console and reload the page. Select Backend environments and then click the API link.
On the API page, note the addition of a UserTable under the Data sources section. Click the View in AppSync button.
On the AppSync page, open the Run a query accordion and click the Run a query button.
This opens a GraphQL Playground that allows you to run live queries and mutations against your GraphQL API. Click the Login with User Pools button and sign in, using the Client ID you copied earlier and the credentials you created for your user. Press Login.
Writing Data
Next, you’ll create a User
model. First, if the Explorer pane is open, close it by clicking the X. Now, in the leftmost pane, add the following code, using the name of your user for username
and the sub you copied earlier for both the id
and sub
fields:
mutation CreateUserMutation { createUser(input:{ id: "389b0b66-f0e3-4907-9b4e-01ac4146bb0b" username: "Lizzie", sub: "389b0b66-f0e3-4907-9b4e-01ac4146bb0b", }) { id username sub createdAt } }
Unfortunately, you can’t add comments to the GraphQL code. The following line numbers refer to those in the screenshot below.
- On line 1, you define a named mutation called
CreateUserMutation
. - In lines 2–5, you run the
createUser
mutation generated by AppSync from your GraphQL schema. The mutation takes a single parameter calledinput
. This parameter contains the username and sub for the user you want to create. - Lines 6–9 define the response to the mutation. You specify that
id
,username
,
sub
andcreatedAt
should be returned in the response. These are all fields of the created user.
Now press the orange Play button to run the mutation and create your user.
Your mutation is sent to your AppSync GraphQL server, and the response appears in the middle column.
Next, select Data Sources in the left-hand menu. Then select the DynamoDB Resource for your UserTable.
Your browser will open a new tab. You’ll see your new DynamoDB database table. Select the Items tab.
The Items tab displays a single record. This is the user you just created. Now, click the record ID link to open the database record for your user.
Congratulations! You’ve just successfully created your first database record in DynamoDB. :]
Reading and Writing AppSync Data From Swift
Running GraphQL mutations in the Playground is fun — but not as fun as running them from your app!
Switch back to Xcode and open AppDelegate.swift. Before the call to Amplify.configure()
, add the following line:
try Amplify.add(plugin: AWSAPIPlugin(modelRegistration: AmplifyModels()))
This tells the Amplify library to add support for AppSync via the API Plug-in and register the models created from your GraphQL schema. Currently, this is just your User
model.
Reading Data From AppSync
At this point, the UserSession
object is just a string representing the user’s name. In this next section, you’ll update the app to retrieve user data from your User
model. You’ll use AppSync to read from your DynamoDB database. This will take quite a bit of refactoring, so don’t worry if you see Xcode errors as you work through this section.
Open UserSession.swift and update the two type declarations for loggedInUser
. Change them from String?
to User?
:
public final class UserSession: ObservableObject {
@Published var loaded = false
// Here
@Published var loggedInUser: User? {
didSet {
loaded = true
}
}
init() {}
// Here
init(loggedInUser: User?) {
self.loggedInUser = loggedInUser
}
}
Next, open AuthenticationService.swift. Add the following method after setUserSessionData(_:)
:
private func fetchUserModel(id: String) -> Future<User, Error> {
// 1
return Future { promise in
// 2
_ = Amplify.API.query(request: .get(User.self, byId: id)) { [self] event in
// 3
switch event {
case .failure(let error):
logger.logError(error.localizedDescription)
promise(.failure(error))
return
case .success(let result):
// 4
switch result {
case .failure(let resultError):
logger.logError(resultError.localizedDescription)
promise(.failure(resultError))
return
case .success(let user):
// 5
guard let user = user else {
let error = IsolationNationError.unexpectedGraphQLData
logger.logError(error.localizedDescription)
promise(.failure(error))
return
}
promise(.success(user))
}
}
}
}
}
This might look a bit scary at first glance, but there’s really not much to it:
- First, this function returns a
Future
, which promises aUser
on successful completion. - You use the Amplify API to run a query. The query will retrieve a
User
object by its ID. - The API takes an event listener closure as its final argument. You issue the call with the result of the network request, which can either succeed or fail. On failure, you log the error before returning the failure.
- If the network request succeeds, you check the underlying GraphQL result type. This could still result in a failure, such as an invalid request, so again you must check for errors.
- If everything succeeds, you confirm that you received a valid user for your ID. If so, you return it.
Now, update setUserSessionData(_:)
to take a User
rather than a String
:
private func setUserSessionData(_ user: User?) {
DispatchQueue.main.async {
if let user = user {
self.userSession.loggedInUser = user
} else {
self.userSession.loggedInUser = nil
}
}
}
Then, in checkAuthSession()
, replace the call to setUserSessionData(authUser.username)
with the following:
let sub = authUser.userId
cancellable = fetchUserModel(id: sub)
.sink(receiveCompletion: { completion in
switch completion {
case .failure(let error):
logger.logError(error)
signOut()
case .finished: ()
}
}, receiveValue: { user in
setUserSessionData(user)
})
This code calls the fetchUserModel(id:)
method you just wrote. On success, it sets the user session with the user.
Similarly, in signIn(as:identifiedBy:)
, replace the call to setUserSessionData(_:)
with the following:
cancellable = self.fetchUserModel(id: authUser.userId)
.sink(receiveCompletion: { completion in
switch completion {
case .failure(let error):
signOut()
promise(.failure(error))
case .finished: ()
}
}, receiveValue: { user in
setUserSessionData(user)
promise(.success(.signedIn))
})
Finally, open RootView.swift. Update the HomeScreenViewModel
initializer in line 62 to use the new UserModel
:
model: HomeScreenViewModel(
userID: loggedInUser.sub,
username: loggedInUser.username)
Build and run. If you’re not already logged in, log in now. Confirm that the app still takes you to the Locations screen.
Nothing has changed in the UI. But your app is now using AppSync to query for the correct User model from the DynamoDB database!
Creating Data in DynamoDB
Earlier, you created a new User
record in DynamoDB by running a mutation in the GraphQL playground. You hard-coded the information for your one user. Obviously, that isn’t a good long-term solution! Instead, you should use Amplify.API
. You’ll make that change now.
Open AuthenticationService.swift and locate the success handler in confirmSignUp(for:with:confirmedBy:)
. Remove the call to checkAuthSession()
, and replace it with the following:
// 1
guard let authUser = Amplify.Auth.getCurrentUser() else {
let authError = IsolationNationError.unexpctedAuthResponse
logger.logError(authError)
promise(.failure(IsolationNationError.unexpctedAuthResponse))
signOut()
return
}
// 2
let sub = authUser.userId
let user = User(
id: sub,
username: username,
sub: sub,
postcode: nil,
createdAt: Temporal.DateTime.now()
)
// 3
_ = Amplify.API.mutate(request: .create(user)) { event in
switch event {
// 4
case .failure(let error):
signOut()
promise(.failure(error))
case .success(let result):
switch result {
case .failure(let error):
signOut()
promise(.failure(error))
case .success(let user):
// 5
setUserSessionData(user)
promise(.success(.signedIn))
}
}
}
This is what your code does:
- First, you get the current user from the Amplify Auth API. If no user is logged in, you return an error and sign out.
- You create a new
User
model object, setting theusername
for your user. You set bothid
andsub
to theuserId
from Cognito. - Then you write this user model record to DynamoDB by calling the
Amplify.API.mutate
API with acreate
request type. - You handle failures from the network layer and then the GraphQL layer, as in previous examples.
- Finally, you set the user session to your newly-created user and return a successful sign-in.
Build and run the app on a different simulator. Sign up as a new user. Confirm that the new user record appears in DynamoDB by refreshing the table in the DynamoDB tab in your browser.
Where to Go From Here?
Congratulations! You’ve used AWS Cognito to add sign-up and sign-in to your app. And you’ve used AWS AppSync to read and write data between your app and a database stored in the cloud, via GraphQL.
You can download the finished project using the Download Material buttons. Remember that you’ll need to perform the Amplify setup for this project, just as you did for the starter project.
You can refer to the Amplify Framework Documentation to find out more about the AWS services available via Amplify. Or check out Part 2 of this tutorial, Using AWS as a Back End: The Data Store & Analytics. In it, you’ll learn how to use the DataStore API to build the rest of the Isolation Nation chat app with real-time updates and user analytics.