AWS Amplify is a client library, CLI toolchain, and UI component library that allows developers to quickly create and connect to powerful services in the cloud. In this post, we’ll look at how to build fully serverless web apps with React and AWS Amplify with features like authentication, a managed GraphQL data layer, storage, lambda functions, and web hosting.
Amplify enables features like managed GraphQL (AWS AppSync), storage (Amazon S3), user authentication (Amazon Cognito), serverless functions (AWS Lambda), hosting (Amazon CloudFront and Amazon S3), analytics (Amazon Pinpoint), and more.
The goal of the library and CLI is to let developers create full-stack web and mobile applications without having to worry about managing their own back-end infrastructure, allowing them to move further up the stack using the skills they already know.
In this series, I’ll show you how to create a new AWS Amplify project, enable cloud features using the CLI, connect the React application, and begin interacting with the cloud services. In this post, I’ll show you how to implement authentication, storage, and hosting. In the next tutorial, we’ll learn how to create and interact with GraphQL and Serverless APIs.
While this tutorial uses React, Amplify will work with any JavaScript project and has framework-specific components for Angular, Vue, React Native, and Ionic. The CLI also supports native iOS and Android.
Getting Started
Create a New React Application
To get started, we first need to create a new React application using the create-react-app CLI and change into the new directory:
npx create-react-app amplify-web-app cd amplify-web-app
Next, we’ll install the AWS Amplify client dependencies:
yarn add aws-amplify aws-amplify-react # or npm install aws-amplify aws-amplify-react
Install and Configure the AWS Amplify CLI
Next, we’ll need to install the AWS Amplify CLI.
npm install -g @aws-amplify/cli
Now that the AWS Amplify CLI is installed, we need to configure it to be able to create resources in our AWS account. We do this by running the amplify configure
command and setting up a new AWS user.
amplify configure
You can see a short video walkthrough of this configuration on YouTube.
Now that the AWS Amplify CLI is installed and configured, run the amplify
command from your command line to see the available options and ensure that the CLI was installed properly.
amplify
Initializing a New AWS Amplify Project
To initialize a new AWS Amplify project, we will run the amplify init
command:
amplify init
When prompted, choose your preferred text editor and stick with the defaults for all of the other options.
This has now initialized a new AWS Amplify project locally, and we will now see an amplify
directory and .amplifyrc
file created in the root directory of our React project. These files hold configuration info about our Amplify project, and we don’t need to touch them at all for now.
Implementing Authentication
The first feature we’ll enable is user authentication. We can enable features at any time by running amplify add
. The category for authentication is auth
, so run:
amplify add auth
When asked Do you want to use the default authentication and security configuration?, choose Yes.
Once this is created, we need to run amplify push
to create the new service in our account:
amplify push
When asked Are you sure you want to continue?, choose Yes.
Once the service has been created, you can view the service in the dashboard at any time by visiting https://console.aws.amazon.com/cognito/users/ and clicking on the name of your service.
We can also view all enabled services at any time by running amplify status
:
amplify status
You will also notice a new file that was created—aws-exports.js—in the root folder of the React app. You will not need to edit this file as it is handled for you by the CLI, but we will be using it in the next step to configure the local project.
Adding Authentication to the React App
Now that we have the authentication service created, we can begin using it in our React app!
The first thing we need to do is configure the React application to know about our Amplify project. The way we do that is by calling Amplify.configure
in the root of the project—for us, that will be src/index.js.
import Amplify from 'aws-amplify' import config from './aws-exports' Amplify.configure(config)
Now, our project is ready to go, and we can implement authentication.
Using the withAuthenticator
Higher-Order Component
We’ll look at a couple of ways to go about implementing user authentication, but to kick things off, we’ll start by using the withAuthenticator
higher-order component from the aws-amplify-react library. This component scaffolds out an entire authentication flow in just a few lines of code and is a great way to get up and running with the library.
In App.js, import the withAuthenticator
HOC at the top of the file:
import { withAuthenticator } from 'aws-amplify-react'
And, at the bottom, update the export
statement to wrap the App
component with withAuthenticator
.
export default withAuthenticator(App)
To learn more, read about the available Amplify React components for authentication in the official documentation.
Testing the Authentication Flow
Now, we can run the app and should see a sign-in screen:
Click Create account to sign up and then sign in to the app. Once we’re signed in, the session will be stored, so we can refresh the page and we will stay signed in.
Sign-Out Options
We can also render a sign-out button by adding a second argument to the HOC:
export default withAuthenticator(App, { includeGreetings: true })
Note that we can also use the Auth
class directly to sign users out:
// 1. import the class import { Auth } from 'aws-amplify' // Sign the user out await Auth.signOut()
Note that when calling Auth.signOut
directly, we must still rerender the component in some way in order to bring the user back to the sign-in page. You can see an example of this in an issue thread on the project’s GitHub repo.
Using the Auth
Class
We can also use the Auth
class to manually manage users. Auth has over 30 available methods including signUp
, signIn
, confirmSignUp
, confirmSignIn
, forgotPassword
, and resendSignUp
.
Let’s take a look at how you might implement user sign-up using the signUp
class method:
// 1. Create initial state to hold user inputs state = {username: '', password: '', email: '', phone_number: '', authCode: ''} // 2. onChange handler for user input changes onChange = e => { this.setState({ [e.target.name]: e.target.value }) } // 3. Function to call Auth.signUp signUp = async () => { const { username, password, email, phone_number } = this.state await Auth.signUp({ username, password, attributes: { phone_number, email} }) console.log('successfully signed up') } // 4. Function to call Auth.signUp confirmSignUp = async () => { const { username, authCode } = this.state await Auth.confirmSignUp(username, authCode) console.log('successfully confirmed signed up') } // 5. In render method, create inputs with attributes to update state // 6. Create buttons to call signUp and confirmSignUp methods
This is a blueprint for how you could manually sign up a user with the Auth class.
Manual implementation takes longer to write but gives you complete control over not only the UI but also the actual functionality you would like to implement.
You can learn more about Authentication with AWS Amplify in the project documentation.
Storage With Amazon S3
Amazon S3 is a popular service for storing media like images and videos, as well as for back-end services like application hosting, backups, and software delivery.
The AWS Amplify CLI enables us to create, configure, update, and delete S3 buckets. In this section, we’ll look at how to create an S3 bucket as well as how to upload and download images and files to the bucket.
To enable Storage, we can run the following command:
amplify add storage
Next, you’ll be prompted to supply some configuration details. Select the Content (Images, audio, video, etc.) service. Next, supply a project-specific resource name (used internally in the project) and bucket name (the S3 location where your data will be stored). Finally, access should be restricted to Auth users only, and authenticated users should be granted read/write access.
Now storage has been added to our configuration, and we run amplify push
to create the new resources in our account:
amplify push
This will create and configure an Amazon S3 bucket that we can start using for storing items.
Example of Using S3 Storage
If we wanted to test this out, we could store some text in a file like this:
import { Storage } from 'aws-amplify' // create function to work with Storage addToStorage = () => { Storage.put('javascript/MyReactComponent.js', ` import React from 'react' const App = () => (Hello World
) export default App `) .then (result => { console.log('result: ', result) }) .catch(err => console.log('error: ', err)); } // add click handler
This will create a folder called javascript in our S3 bucket and store a file called MyReactComponent.js there with the code we specified in the second argument of Storage.put
.
If we want to read everything from this folder, we can use Storage.list
:
readFromStorage = () => { Storage.list('javascript/') .then(data => console.log('data from S3: ', data)) .catch(err => console.log('error')) }
If we only want to read the single file, we can use Storage.get
:
readFromStorage = () => { Storage.get('javascript/MyReactComponent.js') .then(data => console.log('data from S3: ', data)) .catch(err => console.log('error')) }
If we wanted to pull down everything, we could use Storage.list
:
readFromStorage = () => { Storage.list('') .then(data => console.log('data from S3: ', data)) .catch(err => console.log('error')) }
Working With Images
Working with images is also easy. Here’s an example:
class S3ImageUpload extends React.Component { onChange(e) { const file = e.target.files[0]; Storage.put('example.png', file, { contentType: 'image/png' }) .then (result => console.log(result)) .catch(err => console.log(err)); } render() { return ( this.onChange(e)} /> ) } }
In the above code, we link a file upload form input to the onChange
event handler. When the user supplies a file, Storage.put
is called to upload the file to S3 with MIME type image/png
.
Hosting
To deploy and host your app on AWS, we can use the hosting
category.
amplify add hosting
Again, you’ll be prompted to supply some configuration options:
- For the environment type, select DEV (S3 only with HTTP).
- Choose a globally unique bucket name where your project will be hosted.
- Supply the name of the index and error URLs for the website—usually index.html.
Now, everything is set up, and we can publish the app:
amplify publish
Removing Services
If at any time you would like to delete a service from your project and your account, you can do this by running the amplify remove
command and then pushing.
amplify remove auth amplify push
If you are unsure of what services you have enabled at any time, you can run the amplify status
command:
amplify status
amplify status
will give you the list of resources that are currently enabled in your app.
Conclusion
AWS Amplify enables developers to build full-stack, cloud-enabled apps more easily than ever before, allowing developers to iterate quickly, directly from their front-end environment.
This is part one of a two-part series. In the next tutorial, we’ll learn how to create and interact with GraphQL and Serverless APIs. So stay tuned.
Powered by WPeMatico