Welcome to part 4 of this series on user authentication with React Native and AWS Amplify.

If you did not follow the previous parts, I suggest you start here.

You can check the full repo in here.

After three parts where we learned how to design a great layout by using react-navigation and native-base, now is the time to focus on the back-end logic to securely store users info and authenticate them properly.

Let us get started 🏇.

5— AWS Amplify as a back-end service

5.1 — Configuration

If you never worked with AWS Amplify before, make sure you globally install its command-line interface CLI.

Open up your command line terminal and execute the following command.

If you are not yet in the root directory of your project, you need to navigate there. Then, run the following command.

yarn add aws-amplify aws-amplify-react-native

In order to use the Amplify CLI with your project, you must configure the service using an AWS Identity And Management User (IAM).

To do so, run the following.

amplify configure

Please refer to the following video from Nader Dabit to step by step configure your project with Amplify.

At the end of the configuration, you should see a similar message in the terminal.

Amplify configure ended.

Now we need to initialize a new Amplify project. Type the following in the terminal.

amplify init

You will be prompt to choose your favorite code editor (Visual Studio Code in my case), the language of the app (choose javascript), and the framework (choose react-native).

When prompt for source directory type src.

When prompt for default commands just press enter.

When prompt if you’d like to use an AWS profile, choose Yes.

Choose the user profile you have created when you configured the Amplify CLI (if you did not provide a username this would be default).

After the initialization, you should see the following success message in the terminal.

Successful initialization of the Amplify project.

Now that our app is fully integrated with an Amplify back-end, we can start using Amplify services such as authentication as a back-end service with our project.

To add authentication as a back-end service to your project, type the following in the terminal.

amplify add auth

When asked ‘’Do you want to use default authentication and security configuration?’’ choose Yes, use the default configuration.

Now type

amplify push

you should be able to see the following table appear.

comp$ amplify push

| Category | Resource name | Operation | Provider plugin |

| -------- | --------------- | --------- | ----------------- |

| Auth | cognito12345678 | Create | awscloudformation |

? Are you sure you want to continue? (Y/n) Y

After pressing Y, wait a few minutes so the configuration will be pushed to the AWS cloud formation. Finally, you should see the following message in the terminal.

✔ All resources are updated in the cloud

At the same time, a new file, called aws-exports.js, has been generated in your src directory.

Open the file in your editor and have a look at it.

// WARNING: DO NOT EDIT. This file is automatically generated by AWS Amplify. It will be overwritten. const awsmobile = {

"aws_project_region": "####",

"aws_cognito_identity_pool_id": "####",

"aws_cognito_region": "####",

"aws_user_pools_id": "#####",

"aws_user_pools_web_client_id": "####"

}; export default awsmobile;

The aws-exports.js contains all the information related to the back-end service you created in the cloud.

To check if everything is updated in the cloud with respect to your local project, run the following command.

amplify status

The previous table will appear again with the service you have created.

| Category | Resource name | Operation | Provider plugin |

| -------- | --------------- | --------- | ----------------- |

| Auth | cognito12345678 | No Change | awscloudformation |

The configuration has finally come to an end 😚.

Now that our app has AWS Amplify authentication as a back-end service, we can start writing React Native code to interact with its API.

Add the following code inside your App.js file.

// Amplify imports and config

import Amplify from '@aws-amplify/core'

import config from './src/aws-exports'

Amplify.configure(config)

We will adopt a modular import approach to limit the size of our bundle. Check out Nader Dabit article on the subject for more details.

Add the following modular import to the following files: SignUpScreen.js, SignInScreen.js, ForgetPasswordScreen.js, AuthLoadingScreen.js, SettingsScreen.js.

// AWS Amplify

import Auth from '@aws-amplify/auth'

We are now able to interact with the Auth API to sign up, sign in, reset password, sign out, and reclaim a new password when the old one is forgotten.

Time to write some code 😎.

5.2 — Sign up users

Let us start by adding the sign-up process to the SignUpScreen.js file.

Inside the SignUpScreen state, add the following field.

state = {

... same code as before

// users will receive a confirmation code

authCode: '',

}

The sign-up flow will work as the following:

Users will fill their username, email, phone.

Users will receive a confirmation code to verify their email and/or phone.

Users will confirm their email/phone then will be redirected to the sign in screen to authenticate to the app.

The authCode will be used to store the confirmation code that users will receive during the sign-up process.

To perform all of the above, we will add three methods to the SignUpScreen class component.

Sign up, confirm sign up, and resend confirmation code methods.

Let us go through the code above.

We used the Auth.signUp method to register the user’s attributes.

Upon receiving the confirmation code, Auth.confirmSignUp will confirm the user’s and set the account to active. At the same time, it will navigate the user to the sign-in screen using react-navigation.

The Auth.resendSignUp method will resend the confirmation code if you did not receive any.

Remarks

We carefully added errors handling to show the users the proper messages when making mistakes in signing up.

The custom methods we defined (signUp, signIn, forgetPassword ..etc) use the same nomenclature as the methods from the Auth class.

Time to test our sign up flow.

Refresh your app simulator and navigate to the sign-up screen.

Sign up by filling the fields and press the Sign Up button.

When pressing the Sign Up button, you should see the following.

Expo Dev tool and iOS simulator for the sign-up process.

Check your email for the verification code from AWS.

Go to the AWS console, log in to your AWS account and navigate to the Cognito service. Choose User Pools and navigate to the cognito pool you have created for your project (remember the info are in aws-exports.js).

You should see the newly created user under the Users and groups section.

Cognito User Pools. Newly created user.

Notice the Account status field is stating: UNCONFIRMED.

To confirm the user, enter the confirmation code you received by email in the sign-up screen and press the Confirm Sign Up button.

The following will happen.

Expo Dev Tools and iOS simulator when confirming the user sign up.

As you can see, the user has been confirmed and we were redirected to the sign-in screen.

In the AWS console, check again the Account status. You should see is change to CONFIRMED.

5.3 — Sign in users

In the SignInScreen.js file, we had the following dumb function to sign the users in.

async signIn() {

await AsyncStorage.setItem('userToken', '12345')

this.props.navigation.navigate('Authloading')

}

To sign in users, we will now require them to provide their username and their password.

Replace the above code with and Amplify Auth logic like the following.

// Sign in users with Auth

async signIn() {

const { username, password } = this.state

await Auth.signIn(username, password)

.then(user => {

this.setState({ user })

this.props.navigation.navigate('Authloading')

})

.catch(err => {

if (! err.message) {

console.log('Error when signing in: ', err)

Alert.alert('Error when signing in: ', err)

} else {

console.log('Error when signing in: ', err.message)

Alert.alert('Error when signing in: ', err.message)

}

})

}

We used the Auth.signIn method from Amplify to check the username and password. If the check is successful, we navigate the user using react-navigation to the AuthLoadingScreen.

Remark

Amplify Auth already makes use of react-native AsyncStorage internally. As a consequence, the AsyncStorage import we had since part 1 is now redundant and can be removed from all the js files that had it.

5.4 — Remember logged in users

In AuthLoadingScreen.js, we previously used AsyncStorage to remember the logged in users.

componentDidMount = async () => {

await this.loadApp()

} // Remember logged in users

loadApp = async () => {

const userToken = await AsyncStorage.getItem('userToken')

this.props.navigation.navigate(userToken ? 'App' : 'Auth')

}

We will change the above code to grab the userToken from the user object defined by our back-end service when we signed in the user (use console.log(user) to visualize the user object in the console).

First, create and initialize the userToken state by adding this inside the AuthLoadingScreen class component.

state = {

userToken: null

}

Then amend the loadApp to look like this.

// Get the logged in users and remember them

loadApp = async () => {

await Auth.currentAuthenticatedUser()

.then(user => {

this.setState({userToken: user.signInUserSession.accessToken.jwtToken})

})

.catch(err => console.log(err))

this.props.navigation.navigate(this.state.userToken ? 'App' : 'Auth')

}

In the above method, we used the Amplify Auth.currentAuthenticatedUser method to retrieve the user object and store its jwtToken in the userToken state field. Then the same logic used before applies. The app navigates the user based on the presence or not of a userToken.

5.5— Forget password

Now let us build the Forget password functionality.

In ForgetPasswordScreen.js, add two methods: forgetPassword and forgetPasswordSubmit. The below gist shows how the code should look like.

AWS Amplify Auth forget password functionality.

The forgetPassword method calls the Auth.forgetPassword method that takes the username and sends a new confirmation code.

The forgetPasswordSubmit calls the Auth.forgetPasswordSubmit method that takes the username, the confirmation code, and the new password. It will then navigate the user to the sign-in screen.

Call these methods inside the TouchableOpacity components in the render() method of the ForgetPasswordScreen class.

<TouchableOpacity

onPress={() => this.forgotPassword()}

style={styles.buttonStyle}>

<Text style={styles.buttonText}>

Send Code

</Text>

</TouchableOpacity> ... <TouchableOpacity

onPress={() => this.forgotPasswordSubmit()}

style={styles.buttonStyle}>

<Text style={styles.buttonText}>

Confirm the new password

</Text>

</TouchableOpacity>

Time to test this. Refresh your simulator and navigate to the Forget Password screen. You should be able to request a new password as in the following video.

Forget password workflow.

Upon setting the new password, the Expo Dev Tools should print the following message.

Expo Dev Tools log when for forget the password.

5.6 — Reset password

In the SettingsScreen.js file, inside the SettingsScreen class, add the state and initialize it with the following fields.

state = {

password1: '', // old password

password2: '', // new password

}

Then define the changePassword method using the Amplify Auth.currentAuthenticatedUser and Auth.changePassword methods as below.

// Change user password for the app

changePassword = async () => {

const { password1, password2 } = this.state

await Auth.currentAuthenticatedUser()

.then(user => {

return Auth.changePassword(user, password1, password2)

})

.then(data => console.log('Password changed successfully', data))

.catch(err => {

if (! err.message) {

console.log('Error changing password: ', err)

Alert.alert('Error changing password: ', err)

} else {

console.log('Error changing password: ', err.message)

Alert.alert('Error changing password: ', err.message)

}

})

}

In the above logic, we defined a changePassword method. It takes the user object, obtained from the currentAuthenticatedUser method, the old password, the new password, and feeds them to the Auth.changePassword method.

We add the changePassword as an onPress to the TouchableOpacity component of the Submit button.

<TouchableOpacity

onPress={this.changePassword}

style={styles.buttonStyle}>

<Text style={styles.buttonText}>

Submit

</Text>

</TouchableOpacity>

Now we should be able to test the change password functionality.

Navigate to the Settings screen. Type the old and the new password and press Submit. You should see the following response.

Change password functionality.

5.7 — Sign out users

In the SettingsScreen.js, we had the following sign out method.

async singOut() {

await AsyncStorage.clear()

this.props.navigation.navigate('Authloading')

}

Replace this method with the following.

// Sign out from the app

signOutAlert = async () => {

await Alert.alert(

'Sign Out',

'Are you sure you want to sign out from the app?',

[

{text: 'Cancel', onPress: () => console.log('Canceled'), style: 'cancel'},

// Calling signOut

{text: 'OK', onPress: () => this.signOut()},

],

{ cancelable: false }

)

}

// Confirm sign out

signOut = async () => {

await Auth.signOut()

.then(() => {

console.log('Sign out complete')

this.props.navigation.navigate('Authloading')

})

.catch(err => console.log('Error while signing out!', err))

}

When the user presses ‘OK’, the signOutAlert will call the signOut method.

The signOut method calls the Auth.signOut to sign the user out. The user is then redirected back to the Authloading screen.

Otherwise, if the user presses ‘Cancel’, the method won’t do anything and the user will remain in the app.

Finally, we add the signOutAlert to the TouchableOpacity component of the Sing out button.

<TouchableOpacity

style={[styles.buttonStyle, {flexDirection: 'row', justifyContent: 'center'}]}

onPress={this.signOutAlert}>

<Icon name='md-power' style={{color: '#fff', paddingRight: 10}}/>

<Text style={styles.buttonText}>

Sign out

</Text>

</TouchableOpacity>

Users can now sign out from the app. Go test it.

Sign out using AWS Amplify.

Et Voila 😄.

Conclusion

This concludes this series of articles on authentication with React Native and AWS Amplify.

I hope you enjoyed the ride.

We managed to build an authentication app with amazing UI (layout and navigation) and full back-end sign up, sign in, reset password, sign out, and forget password functionalities.

If you enjoyed this tutorial, you can give me as many claps👏 as 50. Hit the follow button to stay updated with the upcoming articles. You can stay updated with my latest open source projects on Twitter and Github.

Take care and see you soon 🙋.

Join our community Slack and read our weekly Faun topics ⬇