The Complete Guide to User Authentication with the Amplify Framework
Tags: awsamplify, react, serverless
Published: 2019-05-01 13:43:00

---
title: The Complete Guide to User Authentication with the Amplify Framework
published: true
description: An in depth guide for adding authentication to your next app using AWS Amplify
tags: AWS Amplify, React, serverless
---
![](https://thepracticaldev.s3.amazonaws.com/i/cyt0msckucqfvbpw2d05.jpg)

The AWS Amplify Authentication modules provide Authentication APIs and building blocks for developers who want to create apps with real-world production-ready user authentication.

With Amplify you can incorporate username / password based authentication as well as OAuth with Facebook, Google or Amazon.

![](https://thepracticaldev.s3.amazonaws.com/i/xujnbctap44h12ovju02.png)

We also provide a pre-built “Hosted UI” that provides a full OAuth + username / password flow.

![](https://thepracticaldev.s3.amazonaws.com/i/ury12fn9kn33obfbahaw.png)

> This post covers authentication for web applications. For the post on React Native, click [here](https://dev.to/dabit3/the-complete-react-native-guide-to-user-authentication-with-the-amplify-framework-ib2).

## Introduction to Amazon Cognito

The Amplify Framework uses [Amazon Cognito](https://aws.amazon.com/cognito/) as the main authentication provider. Amazon Cognito User is a robust user directory service that handles user registration, authentication, account recovery & other operations.

Amplify interfaces with Cognito to store user data, including federation with other OpenID providers like Facebook & Google.

The Amplify CLI automates the access control policies for these AWS resources as well as provides fine grained access controls via GraphQL for protecting data in your APIs.

Most modern applications require multiple authentication options, i.e. Facebook login + Username / password login. Amazon Cognito makes this process easy by allowing you to use a single user registry to authenticate users across multiple authentication types.

In this post, you'll learn how to add authentication to your React application using both OAuth as well as username & password login.

# Getting Started

### Installing the Amplify CLI

To build authentication into your application with Amplify you first need to install the AWS Amplify CLI. The Amplify CLI is a command line tool that allows you to create & deploy various AWS services.

To install the CLI, we'll run the following command:

```sh
npm install -g @aws-amplify/cli
```

Next, we'll configure the CLI with a user from our AWS account:

```sh
amplify configure
```

> For a video walkthrough of the process of configuring the CLI, click [here](https://www.youtube.com/watch?v=fWbM5DLh25U).

### Creating the React project

Next, we'll create the React application we'll be working with:

```sh
npx create-react-app rn-amplify

cd rn-amplify
```

Now, we'll install the Amplify library:

```sh
npm install aws-amplify
```

### Creating the Amplify project

Now we can now initialize a new Amplify project from within the root of our React application:

```sh
amplify init
```

Here we'll be guided through a series of steps:

- Enter a name for the project: __amplifyauth__ (or your preferred project name)
- Enter a name for the environment: __local__ (or your preferred environment name)
- Choose your default editor: __Visual Studio Code__ (or your text editor)
- Choose the type of app that you're building: __javascript__
- What javascript framework are you using: __react__
- Source Directory Path: __src__
- Distribution Directory Path: __build__
- Build Command: __npm run-script build__
- Start Command: __npm run-script start__
- Do you want to use an AWS profile? __Y__
- Please choose the profile you want to use: __YOUR_USER_PROFILE__

Now, our Amplify project has been created & we can move on to the next steps.

# Creating our App IDs

In our app we'll be having three types of authentication:

- Facebook (OAuth)
- Google (OAuth)
- Cognito (username + password)

Next we'll need to create Facebook & Google Apps in order to get an App ID & App Secret for each of them.

For instructions around the __[Facebook](https://developers.facebook.com)__ setup click [here](https://aws-amplify.github.io/docs/js/cognito-hosted-ui-federated-identity#facebook-instructions).

For instructions around the __[Google](https://console.developers.google.com/apis/credentials)__ setup click [here](https://aws-amplify.github.io/docs/js/cognito-hosted-ui-federated-identity#google-sign-in-instructions).

After you've created the Facebook & Google OAuth credentials move on to the next step.

# Creating & configuring the authentication service

Now that our Amplify project has been initialized & we have our App IDs & secrets from Facebook & Google we can add the authentication service. To do so, we can run the following command:

```sh
amplify add auth

# run amplify update auth if you already have a project configured & want to now add Social login
```

This will walk us through a series of steps:

- Do you want to use the default authentication and security configuration? __Default configuration with Social Provider (Federation)__
- How do you want users to be able to sign in when using your Cognito User Pool? __Username__
- What attributes are required for signing up? __Email__
- What domain name prefix you want us to create for you? __amplifyauthXXXXXXXXX__ (use default or create custom prefix)
- Enter your redirect signin URI: __http://localhost:3000/__ (this can be updated later for production environments)
- Do you want to add another redirect signin URI: __N__
- Enter your redirect signout URI: __http://localhost:3000/__ (this can be updated later for production environments)
- Do you want to add another redirect signout URI: __N__
- Select the social providers you want to configure for your user pool: Choose __Facebook__ & __Google__

> In the above step we chose _Default configuration with Social Provider (Federation)_. This will allow a combination of Username / Password signin with OAuth. If you only want Username / Password, you could choose _Default configuration_ or _Manual Configuration_.

Finally, you'll be prompted for your App IDs & Secrets for both Facebook & Google, enter them & press enter to continue.

Now that the authentication service has successfully been configured, we can create the service by running the following command:

```sh
amplify push
```

After running `amplify push` you should see a success message & the __OAuth Endpoint__ should also be logged out to the console:

![](https://thepracticaldev.s3.amazonaws.com/i/mwtmnrmzt0534n01m02a.png)

The OAuth endpoint should look something like this:

```sh
https://amplifyauth8e79c995-8e79c995-local.auth.eu-central-1.amazoncognito.com/
```

This OAuth endpoint is also available for reference in __src/aws-exports.js__ if you need it at any point under the `oauth` -> `domain` key.

We will need to use this endpoint to finish configuring our Facebook & Google Oauth providers.

## Configuring Facebook

Next, open the Facebook app we created earlier & click on __Basic__ in the left hand menu.

![](https://thepracticaldev.s3.amazonaws.com/i/lhnv5cmhie9wpkbpg1jv.png)

Scroll to the book & click Add Platform, then choose Website:

![](https://thepracticaldev.s3.amazonaws.com/i/ql7oyizcxizminti0mle.png)

For the _Site URL), input the OAuth Endpoint URL with `/oauth2/idpresponse` appended into Site URL:

![](https://thepracticaldev.s3.amazonaws.com/i/thj18ote374ct839m7lw.png)

Save changes.

Next, type your OAuth Endpoint into App Domains:

![](https://thepracticaldev.s3.amazonaws.com/i/oonjcdz1534yxos5rt5i.png)

Save changes.

Next, from the navigation bar choose __Products__ and then __Set up from Facebook Login__ & choose __Web__. 

For the __Valid OAuth Redirect URIs__ use the OAuth Endpoint + `/oauth2/idpresponse`. If you're prompted for the site URL, also use this endpoint (i.e. https://amplifyauth8e79c995-8e79c995-local.auth.eu-central-1.amazoncognito.com/oauth2/idpresponse):

![Valid OAuth Redirect URIs](https://thepracticaldev.s3.amazonaws.com/i/0utvmq3ddac35kp456kh.png)

Save changes.

Make sure your app is _Live_ by clicking the __On__ switch at the top of the page.

![](https://thepracticaldev.s3.amazonaws.com/i/a3glwfwhbo1gijtf83k2.png)

## Configuring Google

Now that Facebook has been configured we can now configure Google. To do so, let's go to the [Google Developer Console](https://console.developers.google.com/apis/credentials) & update our OAuth client.

Click on the client ID to update the settings.

Under __Authorized JavaScript origins__, add the OAuth Endpoint.

For the __Authorized redirect URIs__, add the OAuth Endpoint with `/oauth2/idpresponse` appended to the URL:

![](https://thepracticaldev.s3.amazonaws.com/i/u0wdz5dxteg27upjaqsx.png)

Save changes.

# Testing it out

Now, we should have our authentication service set up & ready to go. Let's test it out.

The easiest way to do this will be by using the `Auth.federatedSignIn()` method from the `Auth` class from AWS Amplify. This function will render the __Hosted UI__ that will give users the option to sign up & sign in with Facebook, Google, or Username / Password without us having to write any of the code.

![](https://thepracticaldev.s3.amazonaws.com/i/ury12fn9kn33obfbahaw.png)

To try this out, let's first configure the React application to recognize our Amplify project. We do this by adding the following code below our last import in __src/index.js__:


```js
// src/index.js

import Amplify from 'aws-amplify'
import config from './aws-exports'
Amplify.configure(config)
```

Next, open App.js & update the code to the following:

```js
// src/App.js

import React from 'react'
import logo from './logo.svg'
import './App.css'

import { Auth } from 'aws-amplify'

function App(props) {
  return (
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <p>
          Edit <code>src/App.js</code> and save to reload.
        </p>
        <button onClick={() => Auth.federatedSignIn()}>Sign In</button>
      </header>
    </div>
  )
}

export default App
```

Now, run the app:

```sh
npm start
```

Now, when the app launched we should be able to sign in using the Sign In button!

## Adding more features

Now that we've added an easy way to sign in, what are the next steps? We will walk through the following:

1. Learn how to sign out users & check the current signed in user
2. Adding custom buttons for OAuth providers
3. How to add custom form for Username / Password sign in with an example
4. Listening to authentication changes (triggers when an authentication event happens)

### How to sign out users & check the current signed in use

Now that we have users signed in, how do we know that they are indeed signed in? We can check for the status of a currently signed in user at any time using the `Auth` class from Amplify.

Let's update our code to the following so we can add a __Sign Out__ button as well as a button to check the status of the currently signed in user:

```js
// src/App.js

import React from 'react'
import logo from './logo.svg'
import './App.css'

import { Auth } from 'aws-amplify'

function checkUser() {
  Auth.currentAuthenticatedUser()
    .then(user => console.log({ user }))
    .catch(err => console.log(err))
}

function signOut() {
  Auth.signOut()
    .then(data => console.log(data))
    .catch(err => console.log(err))
}

function App(props) {
  return (
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <p>
          Edit <code>src/App.js</code> and save to reload.
        </p>
        <button onClick={() => Auth.federatedSignIn()}>Sign In</button>
        <button onClick={checkUser}>Check User</button>
        <button onClick={signOut}>Sign Out</button>
      </header>
    </div>
  )
}

export default App

```

Now when we run our app we're able to log out information about the currently signed in user as well as sign the user out.

### Adding custom buttons for OAuth providers

What if we don't want to use the Hosted UI & want to create our own UI from scratch? We can do this pretty easily. The `Auth` class also has a few methods that we can use to call OAuth providers directly:

```js
Auth.federatedSignIn({provider: 'Google'})
Auth.federatedSignIn({provider: 'Facebook'})
```

Let's update our app to have a couple of custom OAuth buttons:

```js
<button
  onClick={() => Auth.federatedSignIn({provider: 'Facebook'})}
>Sign In with Facebook</button>

<button
  onClick={() => Auth.federatedSignIn({provider: 'Google'})}
>Sign In with Google</button>
```

Now, we have created a custom button for signing in with our OAuth providers.

If you're interested in a live demo of this along with the code, check out [amplifyauth.dev](https://www.amplifyauth.dev/) & view the code in GitHub [here](https://github.com/dabit3/amplify-auth-demo).

### Adding a custom form for Username / Password sign in

What if we wanted to also create a custom form for signing in users? We can do that using our existing configuration using the Auth class.

The Auth class has over 30 methods available for managing users for all authentication tasks like signing users up, signing users in, handling MFA, & all of the functionality that goes along with user management in general. (View AuthClass API [here](https://aws-amplify.github.io/amplify-js/api/classes/authclass.html)).

To get started with a custom form using our existing setup, you can use the following methods to sign users up, confirm sign up (MFA), & sign users in:

```js
// sign user up
Auth.signUp({
  username: someUsername, password: somePassword, attributes: { email: someEmail }
})

// confirm sign up
Auth.confirmSignUp(someUsername, authenticationCode)

// sign user in
Auth.signIn(someUsername, somePassword)
```

These methods are asynchronous & return promises so you can check to see whether they were successful or not.

To view a custom form using this flow, check out [this](https://github.com/dabit3/amplify-auth-demo/blob/master/src/Form.js) file.

If you're interested in a live demo of this along with the code, check out [amplifyauth.dev](https://www.amplifyauth.dev/) & view the code in GitHub [here](https://github.com/dabit3/amplify-auth-demo).

You can also check out [this repo](https://github.com/aws-samples/aws-amplify-auth-starters) for end to end examples in different frameworks, complete with protected routes using a custom authentication flow.

### Listening to authentication events

Now that we have our users signing in & signing out, what if we want to perform some type of action based on this signed in state? We can listen for all authentication changes easily using the Amplify library.

The class we will be using for this is [Hub](https://aws-amplify.github.io/docs/js/hub).

Let's create a listener that listens for all auth events & logs them out:

```js
// src/App.js

// import useEffect hook
import React, { useEffect } from 'react';
import logo from './logo.svg';
import './App.css';

// import Hub
import { Auth, Hub } from 'aws-amplify'

function checkUser() {
  Auth.currentAuthenticatedUser()
    .then(user => console.log({ user }))
    .catch(err => console.log(err));
}

function signOut() {
  Auth.signOut()
    .then(data => console.log(data))
    .catch(err => console.log(err));
}

function App(props) {
  // in useEffect, we create the listener
  useEffect(() => {
    Hub.listen('auth', (data) => {
      const { payload } = data
      console.log('A new auth event has happened: ', data)
       if (payload.event === 'signIn') {
         console.log('a user has signed in!')
       }
       if (payload.event === 'signOut') {
         console.log('a user has signed out!')
       }
    })
  }, [])
  return (
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <p>
          Edit <code>src/App.js</code> and save to reload.
        </p>
        <button onClick={() => Auth.federatedSignIn()}>Sign In</button>
        <button onClick={checkUser}>Check User</button>
        <button onClick={signOut}>Sign Out</button>
        <button onClick={() => Auth.federatedSignIn({provider: 'Facebook'})}>Sign In with Facebook</button>
        <button onClick={() => Auth.federatedSignIn({provider: 'Google'})}>Sign In with Google</button>

      </header>
    </div>
  );
}

export default App

```

Now whenever a user performs any authentication event, the authentication data will be logged out to the console.

# Next Steps

Now that you've added authentication to you app you can begin adding secure backends & APIs to your app with GraphQL or AWS Lamba. To learn more, click [here](https://aws-amplify.github.io/docs/js/api).

If you'd like to host your app using the Amplify Console, click [here](https://console.aws.amazon.com/amplify/home?#/create) or check out [this](https://www.youtube.com/watch?v=DHLZAzdT44Y) video to learn how.

> My Name is [Nader Dabit](https://twitter.com/dabit3). I am a Developer Advocate at Amazon Web Services working with projects like [AWS AppSync](https://aws.amazon.com/appsync/) and [AWS Amplify](https://aws-amplify.github.io/). I specialize in cross-platform & cloud-enabled application development.