Главная » Статьи » Детальная двухфакторная аутентификация React

Детальная двухфакторная аутентификация React

Детальная двухфакторная аутентификация React

От автора: как выполняется двухфакторная аутентификация (как SMS, так и TOTP) с использованием React, React Router и Amazon Cognito. В этом посте мы рассмотрим, как внедрить реальную регистрацию и авторизацию пользователя с двухфакторной аутентификацией параллельно с маршрутизацией и потоком аутентификации в веб-приложении React.

Когда пользователь выйдет из системы, мы будем защищать определенные роуты, перенаправлять их для входа в систему и разрешать доступ к этим защищенным роутам только при входе пользователя в систему. Также мы проверим, изменив роут, останется ли пользователь на странице, или будет перенаправлен на вход / регистрацию.

Детальная двухфакторная аутентификация React

Инструменты, которые мы будем использовать, — это приложения Create React, Glamour для стилизации, React Router для маршрутизации, Amazon Cognito для аутентификации и AWS Amplify для взаимодействия с услугами AWS.

В части 1 будет показано, как настроить поставщика аутентификации и методы, которые будут взаимодействовать с провайдером и регистрировать пользователя.

Часть 2 посвящена тому, как добавить React Router и реализовать поток аутентификации, включая защищенные роуты, выключение, TOTP и т. д.

Создание проекта и установка зависимостей

Первое, что мы сделаем, это создадим новый проект, установим зависимости и настроим поставщика аутентификации.

Давайте создадим проект React с помощью Create React App и перейдем в каталог нового проекта:

create-react-app react-auth
cd react-auth

Затем установим React Router и Glamour с использованием npm или yarn:

yarn add react-router-dom glamor

Или

npm i react-router-dom glamor --save

Добавление поставщика идентификации

Вы можете использовать любой поставщик идентификации, который захотите, но мы будем использовать Amazon Cognito вместе с библиотекой AWS Amplify JavaScript и AWSMobile CLI, чтобы автоматически генерировать ресурсы из командной строки.

Если поставщик еще не установлен, установите AWMobile CLI:

npm i -g awsmobile-cli

Затем сконфигурируйте CLI с учетными данными AWS IAM (нажмите здесь, чтобы просмотреть видеоролик о том, как создавать учетные данные и настраивать CLI):

awsmobile configure

Теперь мы создадим новый проект (выберите значение по умолчанию для всех параметров и придумайте название для проекта, если хотите)

awsmobile init

Это создаст новый проект Mobile Hub, а также файл aws-exports.js в каталоге src. Затем добавим user-signin (Amazon Cognito) и развернём новую конфигурацию:

awsmobile user-signin enable
awsmobile push

awsmobile user-signin запустит Amazon Cognito в проекте с настройками по умолчанию, включая двухфакторную аутентификацию с помощью SMS (TOTP мы добавим позже). Если вы хотите контролировать, как создается поставщик аутентификации, вы можете или передать флажок -p, чтобы указать более подробную конфигурацию ( awsmobile user-signin enable -p ), или перейти в Amazon Cognito, чтобы напрямую создавать и настраивать сервис.

Добавление и тестирование регистрации рядового пользователя

Давайте добавим базовую форму регистрации пользователя в приложение, чтобы узнать, можем ли мы зарегистрировать пользователя.

Детальная двухфакторная аутентификация React

Мы будем работать с Auth- классом от AWS Amplify для взаимодействия с Amazon Cognito. У Auth есть несколько разных методов, позволяющих всем пользователям регистрироваться и входить в систему для изменения и получения паролей и всего прочего.

Основными методами, которые мы будем использовать, следующие:

signUp — регистрирует нового пользователя

signUp(username: string, password: string, attributes?: object)

confirmSignUp — отправляет двухфакторную аутентификацию для нового пользователя

confirmSignUp(username: string, authenticationCode: string)

signIn – авторизовывает существующего пользователя

signIn(username: string, password: string)

confirmSignIn — отправляет двухфакторную аутентификацию для входа пользователя

confirmSignIn(user: object, authenticationCode: string)

Теперь рассмотрим это! Первое, что нам нужно сделать, это настроить AWS Amplify в корне проекта, src/index.js:

// other imports not shown
import config from './aws-exports'
import Amplify from 'aws-amplify'
Amplify.configure(config) ReactDOM.render(<App />, document.getElementById('root'))
registerServiceWorker()

Мы начнем внедрять авторизацию, разрешив пользователям зарегистрироваться.

Давайте создадим новый компонент SignUp.js и поместим его в каталог src. Сейчас мы создаём базовую форму, которая позволит пользователям зарегистрироваться:

import React from 'react'
import { css } from 'glamor'
class SignUp extends React.Component { render() { return ( <div {...css(styles.container)}> <h2>SignUp</h2> </div> ) }
}
const styles = { container: { display: 'flex', flexDirection: 'column', alignItems: 'center' }
}

Затем добавим состояние:

class SignUp extends React.Component { state = { username: '', password: '', email: '', phone_number: '', authCode: '' } // rest of the class
}

Мы добавили элементы, которые нужны, чтобы создать пользователя и разрешить двухфакторную аутентификацию. Нам также необходимо будет создать материалы, которые позволят получить информацию о пользователе, а также код авторизации. Когда пользователь регистрируется с использованием метода signUp , он получает код авторизации через SMS, и ему нужно будет ввести это значение в форму, тогда мы подтвердим, что этот код верен, вызвав confirmSignUp:

Детальная двухфакторная аутентификация React

Давайте теперь создадим входы, кнопки и метод onChange который будет записывать вход в состояние:

import React from 'react'
import { css } from 'glamor' class SignUp extends React.Component { state = { username: '', password: '', email: '', phone_number: '', authCode: '' } onChange = (key, value) => { this.setState({ [key]: value }) } render() { return ( <div {...css(styles.container)}> <h2>Sign Up</h2> <input {...css(styles.input)} placeholder='Username' onChange={evt => this.onChange('username', evt.target.value)} /> <input {...css(styles.input)} placeholder='Password' type='password' onChange={evt => this.onChange('password', evt.target.value)} /> <input {...css(styles.input)} placeholder='Email' onChange={evt => this.onChange('email', evt.target.value)} /> <input {...css(styles.input)} placeholder='Phone Number' onChange={evt => this.onChange('phone_number', evt.target.value)} /> <div {...css(styles.button)}> <span>Sign Up</span> </div> <input {...css(styles.input)} placeholder='Authentication Code' onChange={evt => this.onChange('authCode', evt.target.value)} /> <div {...css(styles.button)}> <span>Confirm Sign Up</span> </div> </div> ) }
} let styles = { container: { display: 'flex', flexDirection: 'column', alignItems: 'center' }, button: { width: '170px', padding: '10px 0px', backgroundColor: '#ddd', cursor: 'pointer', borderRadius: '3px', ':hover': { backgroundColor: '#ededed' } }, input: { height: 40, marginBottom: '10px', border: 'none', outline: 'none', borderBottom: '2px solid #4CAF50', fontSize: '16px', '::placeholder': { color: 'rgba(0, 0, 0, .3)' } }
} export default SignUp

Теперь мы создали наш пользовательский интерфейс, и нам нужно сделать только одно: вызвать методы Auth для регистрации и подтверждения нашего пользователя, поэтому давайте добавим их в несколько методов класса:

 // previous imports omitted import { Auth } from 'aws-amplify' // previously shown code omitted signUp = () => { const { username, password, email, phone_number } = this.state Auth.signUp({ username, password, attributes: { email, phone_number } }) .then(() => console.log('successful sign up!')) .catch(err => console.log('error signing up: ', err)) } confirmSignUp = () => { Auth.confirmSignUp(this.state.username, this.state.authCode) .then(console.log('successful confirm sign up!')) .catch(err => console.log('error confirming signing up: ', err)) } render() { // // here we need to update the buttons to attach class methods to onClick event <div {...css(styles.button)} onClick={this.signUp}> <span>Sign Up</span> </div> <input {...css(styles.input)} placeholder='Authentication Code' onChange={evt => this.onChange('authCode', evt.target.value)} /> <div {...css(styles.button)} onClick={this.confirmSignUp}> <span>Confirm Sign Up</span> </div> }

Наконец, мы импортируем и используем этот компонент в App.js:

import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css'; import SignUp from './SignUp' class App extends Component { render() { return ( <div className="App"> <header className="App-header"> <img src={logo} className="App-logo" alt="logo" /> <h1 className="App-title">Welcome to React</h1> </header> <SignUp /> </div> ); }
} export default App;

Теперь давайте всё это опробуем. Вы должны иметь возможность зарегистрироваться, получить SMS с кодом авторизации, затем ввести код и получить подтверждение на консоли.

Где сейчас находятся данные пользователя? Мы можем видеть их на консоли. Чтобы проверить это, перейдите на панель управления Amazon Cognito , нажмите «Manage your User Pools», а затем выберите имя своего приложения и нажмите «Users and Settings». Там вы можете просмотреть список пользователей, которые зарегистрировались в приложении.

Детальная двухфакторная аутентификация React

Теперь можно авторизовать пользователя! Процесс авторизации очень похож на регистрацию. Мы объединяем юзернэйм и пароль пользователя и вызываем Auth.signIn (username, password), который в случае успеха возвращает объект пользователя и отправляет SMS-сообщение с кодом авторизации. Затем мы можем взять имя пользователя и номер подтверждения и отправить подтверждение:

signIn() { Auth.signIn(this.state.username, this.state.password) .then(user => this.setState({ user })) .catch(err => console.log('error signing in! :', err))
}
confirmSignIn() { Auth.confirmSignIn(this.state.user, this.state.authCode) .then(userData => { console.log('userdata: ', userData) }) .catch(err => console.log('error confirming sign in!: ', err))
}

Этот код работает, но ещё нужно выполнить правильный вход пользователя (во второй части), добавив маршруты в приложение. Не стесняйтесь испытывать его и смотреть, можете ли вы заставить код работать, прежде чем увидите мою реализацию в части 2.

confirmSignIn вернет объект пользователя со всеми данными, включая юзернэйм и уникальный идентификатор (sub, который останется уникальным, даже если пользователь удалит свою учетную запись, а новый пользователь зарегистрируется c тем же юзернэймом).

Если бы мы хотели получить доступ к данным пользователя в приведенном выше ответе, мы могли бы получить его из userData.signInUserSession.idToken.payload, и выглядеть это будет так:

Детальная двухфакторная аутентификация React

Существует несколько способов получения этих данных в любой момент после входа пользователя в систему, включая Auth.currentAuthenticatedUser(). Для полного API Auth нажмите здесь.

После входа пользователя в систему сеанс сохраняется в localStorage помощью Amplify до тех пор, пока он не вызовет метод Auth.signOut . Таким образом, пользователь может покинуть страницу, вернуться и все равно войти в систему!

Во второй части мы продолжим добавление маршрутизации и стилей, а также TOTP, чтобы вы могли работать с Google Authenticator или вашим провайдером TOTP сравнивая с SMS!

Автор: Nader Dabit

Источник: https://hackernoon.com/

Редакция: Команда webformyself.