1. 程式人生 > >React Native Authentication in Depth

React Native Authentication in Depth

Over the past year or so, I have been working with many companies around the world as a consultant with React Native Training. By far the number one question was how to properly implement real world user authentication.

There are many reasons for this, but it really comes down to two major ones in my opinion:

  1. Many developers & companies are coming into React Native from the web where routing and navigation differ substantially.
  2. State management matters a lot when reasoning about authentication in a React Native Application, and many developers & companies coming into React Native are learning both state management as well as navigation at the same time that they are learning the framework.

Even for seasoned React Native developers, implementing authentication with React Native has not been easy or straight forward up until now.

In this post, I hope to greatly simplify what has been up until this point a somewhat complicated task using some state of the art tooling along with clear and concise instructions.

This is a two part series.

In Part 1, we will wire up full user sign up and sign in using a real service, Amazon Cognito with AWS Amplify, allowing users to sign in with username + Password with two factor phone authentication.

This will get you most of the way as far as authentication functionality, while part two will focus on Navigation and state flow.
Amplify supports many category scenarios such as Auth, Analytics, APIs and Storage as outlined in this Developer Guide, but we are really only worried about Auth for purposes of this post.

In Part 2, we will continue using this project and will add a real world navigation flow that I have used many times in production as well as some nice styling. This will include Redux + React-Navigation.

To see the code for the final version of what we will be building in part 1, check out this repo

Getting Started

The first thing we need to do to get started is create a new React Native app and install any dependencies we will be needing:

react-native init RNAuth
You can also use create-react-native-app with Expo, as the expo team has integrated Amplify into the Expo SDK. If you choose this route, please ignore the step that calls for linking the react native project.

Next, we will change into the newly created project and install our dependencies using yarn or npm:

yarn add aws-amplify react-navigation redux react-redux redux-thunk

Next, we need to link the Cognito SDK, which is a dependency of aws-amplify:

react-native link amazon-cognito-identity-js

Now that the dependencies are installed and linked, we will need to create a src directory in the root of the project, src to hold the future project files:

mkdir src

Next we need to configure our AWS credentials.

We can either do this manually in the Cognito console, or we can automate this using the AWSMobile CLI. I recommend using the CLI unless you already know how Cognito works.

Automated Configuration

First, we need to install AWS Mobile CLI:

npm install -g awsmobile-cli

Next, we need to configure the CLI to use your correct credentials.

Run the following command:

awsmobile configure

This will configure the IAM role of the user you will be working with. This will be the accessKeyId, & secretAccessKey of the user, as well as the region you would like to use.

If you already have the AWS cli installed and credentials configured, the cli will automatically have populated this configuration into your AWS Mobile configuration, which you can always override with the same command (awsmobile configure).

To see how to create a new IAM user and configure the CLI, check out the following video.

Next, we will run the awsmobile init command.

awsmobile init

You can choose defaults for all question answers

Running this command enables your Mobile Hub project with default features (Analytics, Hosting & Streaming), adds aws-amplify to your package.json, and adds a config file in your src directory src/aws-config.js.

  1. Analytics, for receiving the analytics sent from your app.
  2. Hosting and Streaming for easily hosting your app in the cloud.
  3. If you do not already have the aws-amplify library installed, it will install it

Finally, we will enable user sign in by running the following command:

awsmobile user-signin enable
awsmobile push

Here is a full videowalk through of the automated configuration:

Manual Configuration

If you already set up your project using the automated configuration above, you can skip to the next section: Implementation of Sign Up with MFA.

In Cognito, we need to create a new user pool and federated identity.

First, create a Cognito User Pool with the following rules:

  • Allow sign in with verified email address
  • Allow sign in with verified phone number
  • Attributes should include email and phone number
  • Multi-Factor Authentication required, with SMS being the second factor we want to enable
  • Verification should be set to both email and phone number
  • We also need to create an App Client for us to use as our federated identity. Make sure to leave the Generate client secret box unchecked.

Second, create an Identity Pool using Cognito as the Identity Provider. Pass in the User Pool ID and App client id we just created in Cognito.

In the src directory of the project, create a new file called aws-exports.js with the following information:

const config = {
identityPoolId: '<Cognito Identity Pool ID>',
region: '<Region>',
userPoolId: '<Cognito User Pool ID>',
userPoolWebClientId: '<Cognito App Client ID>'
}

To see this manual configuration step by step, check out the following video:

Implementation of Sign Up with MFA

Now that the project is set up, we can go ahead and write some code.

The first thing we will do is import the aws-exports.js configuration object in to our App.js file and configure Amplify to work with the configuration:

// App.js, below React Native Imports
import Amplify, { Auth } from 'aws-amplify'
import config from './src/aws-exports'
Amplify.configure(config)

Next, we need to create two class methods to handle the sign up process.

The user needs to sign up (with username, password, email, and phone number), then we need to authenticate the user using their phone number.

Once the user has successfully signed up, Cognito will send an sms to the user that we will need to send back to the API to confirm the user is authenticated.

We need to have a form input with some state that will keep up with the input code once we have it.

To handle all of this, we’ll have three methods: signIn, confirmUser, and onChangeText. We’ll create a state variable called authCode and keep up with it in the onChangeText method for input of the auth code:

export default class App extends Component<{}> {
state = { // 1
authCode: ''
}
onChangeText(authCode) { // 2
this.setState({ authCode })
}
signUp() {
Auth.signUp({ // 3
username: 'myCoolUsername',
password: '[email protected]!',
attributes: {
phone_number: '+15555555555',
email: '[email protected]'
}
})
.then(res => {
console.log('successful signup: ', res)
})
.catch(err => {
console.log('error signing up: ', err)
})
}
confirmUser() { // 4
const { authCode } = this.state
Auth.confirmSignUp('myCoolUsername', authCode)
.then(res => {
console.log('successful confirmation: ', res)
})
.catch(err => {
console.log('error confirming user: ', err)
})
}

// rest of code
}
  1. Create a state object with an authCode property
  2. onChangeText will keep up with the TextInput value that will take in the authentication code once we get it.
  3. signUp calls the Amplify Auth.signUp function, passing in some hardcoded values (for now). Later once we verify this is all working, we will change these hardcoded values to be dynamic from other text inputs. If this signs up the user correctly, the phone number provided should receive an sms with the confirmation code, which we’ll use in the next step. This returns a promise, which we handle by logging out the returned values or handling the error.
  4. confirmUser will take the sms confirmation that we type into the TextInput, and call the Auth.confirmSignUp function, passing in the username as the first argument, and the authCode as the second argument. This also returns a promise which we handle.

Now that the functionality is set up, we need to wire up our UI to work with these methods.
First, let’s go ahead and import Button and TextInput from 'react-native':

import {
// ..existing imports commented out
Button,
TextInput
} from 'react-native'

Now, let’s update the UI to have a SignUp Button, a TextInput, and a Confirm User button.

Let’s change the render method to return the following:

render() {
return (
<View style={styles.container}>
<Button title='Sign Up' onPress={this.signUp.bind(this)} />
<TextInput
placeholder='Input Code'
onChangeText={value => this.onChangeText(value)}
style={styles.input}
/>
<Button
title='Confirm User'
onPress={this.confirmUser.bind(this)}
/>
</View>
)
}

For the style, we will update the container style to remove the alignItems property and create a new input style for the text input:

const styles = StyleSheet.create({
input: {
height: 50,
backgroundColor: '#ededed',
marginVertical: 10
},
container: {
flex: 1,
justifyContent: 'center',
backgroundColor: '#F5FCFF'
}
})

Congratulations, you have successfully integrated some basic authentication into your React Native app, you should now be able to test this out!

Sign In with MFA

Now, let’s take a look at how some basic login functionality could easily be added:

signIn() { // 1
Auth.signIn(username, password)
.then(user => {
// save user in state somewhere
})
.catch(err => {
console.log('error signing in: ', err)
})
}
confirmSignIn() { // 2
Auth.confirmSignIn(user, authCode)
.then(user => {
console.log('user: ', user)
}).catch(err => {
console.log('error confirming sign in: ', err)
})
}

If you have a successful sign up and confirmation, you should be able to go into the console at https://console.aws.amazon.com/cognito/ , find the User Pool that was created (it should start with the name of your React Native project unless you configured this manually or changed it in some way), and view the user that was just created.

If you want to view this entire setup process end to end, check out one of the above videos.

To see the a final version of the above app, check out this repo

In part two, we will continue this authentication process to add better UI as well as integrating Navigation.

If you like React and React Native, checkout out our podcast — React Native Radio on Devchat.tv.
Also, check out my book, React Native in Action now available from Manning Publications.
If you enjoyed this article, please recommend and share it! Thanks for your time.

相關推薦

React Native Authentication in Depth

Over the past year or so, I have been working with many companies around the world as a consultant with React Native Training. By far the number one questi

編譯依賴於React Native0.46.4的工程,報錯“react-native-xcode.sh now lives in a different location”

webstorm alt where git span command com pen app 我的環境: WebStorm 2017.2Build #WS-172.3317.70, built on July 14, 2017 JRE: 1.8.0_152-release

windows上react-native run-android時Exception in thread "main" java.lang.IllegalArgumentException: MALFORMED報錯

andro 重新 ive div alt 刪除 ima 用戶 文件夾 報錯如圖 解決 在C:\Users\{用戶名}\.gradle\wrapper\dists路徑下,刪除所有文件夾,重新run-android ps:網上搜了說是說是java解壓縮編碼格式問題什麽的,感覺

[React Native] Reduce Long Import Statements in React Native with Absolute Imports

other absolute fig Go react project only port gen In large React Native projects, it’s common to have long relative import paths li

[vscode react-native] xcrun: error: unable to find utility "instruments", not a developer tool or in

執行環境:Mac + vscode + xcode IOS ReactNative執行的時候出現這個錯誤 使用vscode執行reactnative 專案時報錯:xcrun: error: unable to find utility "instruments", not a develop

react-native Could not find "store" in either the context or props

1.參考 https://stackoverflow.com/questions/35420989/could-not-find-store-in-either-the-context-or-props 2.在所有需要繫結Redux的檔案中使用connect 容器元件使用 connect() 方法連線 R

React Native ListView警告:in next release empty section headers ...

升級React Native到最新版本出現了一個Warning: Warning:In next release empty section headers will be rendered. In this release you can use 'enableEmptySections

React Higher Order Components in depth

Inheritance InversionInheritance Inversion (II) is implemented trivially like this:As you can see, the returned HOC class (Enhancer) extends the WrappedCom

How to structure your project and manage static resources in React Native

How to structure your project and manage static resources in React NativeReact and React Native are just frameworks, and they do not dictate how we should

Routing in React Native apps and how to configure your project with React

Tab Navigator implements a type of navigation that exists in native iOS for many years already. Recently, Android added it to its Material design patterns

location and App Permissions in React Native and Expo

In web, Geolocation is provided as an API that has different methods to use in a web application. Similarly, React Native takes advantage of this API and i

Setting up ESLint and EditorConfig in React Native projects

Setting up ESLint and EditorConfig in React Native projectsI had a hard time going from 4 spaces to 2 spaces indentation, now I’m quite comfortable with it

Position element at the bottom of the screen using Flexbox in React Native

Position element at the bottom of the screen using Flexbox in React NativeSource: British AirwaysReact Native uses Yoga to achieve Flexbox style layout, wh

React Native in Tezign

苑永志   特贊前端總監,技術愛好廣泛,做過Java,寫過頁面,正在搞Node.js。目前負責特贊前端團隊的人才培養和特贊服務閘道器的開發、維護。喜歡羽毛球、籃球等各種球類運動。 這是苑永志老師在7.8日iTechPlus前端大會上講的內容,整理如下: 特贊是從201

Progressive Image Loading in React Native

Progressive Image Loading in React NativeInternet connection speeds are variable, especially when you’re working with mobile devices. As developers we ofte

React Native demo執行報錯:Cannot find entry file index.android.js in any of the roots

android執行GaGaMall出現如圖錯誤,怎麼弄都不行,index.android.js明明在根目錄的,頭疼的要死...可是同事那邊下的,在npm install後,拷貝過來又行了... 然後想了想,我原來是用cnpm install安裝的,可能是cnpm出了問題,

react-native報錯解決方法 in next release empty section headers will be rendered

當升級完react-native的版本時,run-android的時候會報警告in next release empty section headers will be rendered... 解決方法是:  在ListView下 加個 enableEmptySect

關於Webstorm運行react-native中的Android項目出錯的解決辦法

tor per ive studio 解決 出錯 nat sdk 關於 復制使用androidstudio創建的項目中的local.properties文件至android目錄下 或者直接在android目錄下創建local.properties文件 ndk.dir=D\:

React Native環境配置之Windows版本搭建

services 就會 wrapper function 新建項目 之前 path ont 系統 接近年底了,回想這一年都做了啥,學習了啥,然後突然發現,這一年買了不少書,看是看了,就沒有完整看完的。悲催。然後,最近項目也不是很緊了,所以抽空學習了H5。自學啃書還是很無趣的

React-Native在gitHub下載的Demo不能運行問題!!!

2.4 ida 項目路徑 正常 use native clas log 設置 1、目前找到的最可行的運行React-Native Demo的解決方案 請參考:http://blog.csdn.net/shubinniu/article/details/52873250