AWS AmplifyのAdmin UIで認証機能を実装する

 [AWS Amplifyで自動デプロイとカスタムドメインの設定を試してみる](https://qiita.com/basio/items/ad89977174669cac57aa)の続きで、AWS AmplifyでデプロイしているReactアプリケーションに認証機能を実装してみます。
[公式の手順](https://aws.amazon.com/jp/getting-started/hands-on/build-react-app-amplify-graphql/)ではうまく行かなかったり、Admin UIを使ってみたかったりということで、まとめてみました。

# Amplify CLIの設定
まず、Amplify CLIのインストールおよび初期設定を行います。
ローカル環境のReactアプリケーションでも、Amplifyのバックエンド機能を使用するために必要な作業です。

## Amplify CLIのインストール
npmコマンドでAmplify CLIをインストールします。
最新版（当時Ver.4.41.2）ではうまく行かないので、問題なく動く過去バージョンを取得

```console
npm install -g @aws-amplify/cli@4.36.2
```

## Amplify CLI Configure

```console
amplify configure
```

ブラウザが立ち上がるのでサインインします。

```console
Sign in to your AWS administrator account:
https://console.aws.amazon.com/
Press Enter to continue
(node:8116) ExperimentalWarning: The fs.promises API is experimental
```

AWS Regionは`ap-northeast-1`を選択、usernameはデフォルト（amplify-******）とします。

```console
Specify the AWS Region
? region:  ap-northeast-1
Specify the username of the new IAM user:
? user name:  amplify-eRkjp
```

上記でエンターを押すと、ブラウザでIAMの画面が開きます。
IAMのコンソールで、上記で指定したユーザーを作成し、AdministratorAccess権限を与えます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/556091/4f38867f-9083-fdaa-9323-b370d1c99880.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/556091/e70f872a-d7fd-3adb-1c4e-fb0ddfa95638.png)

作成されたユーザーのアクセスキーとシークレットアクセスキーを入力します。

```console
Enter the access key of the newly created user:
? accessKeyId:  ********************
? secretAccessKey:  ****************************************
This would update/create the AWS Profile in your local machine
? Profile Name:  default

Successfully set up the new user.
```


# バックエンドの設定
## Backend environmentsの初期化
~~AWS Amplify ConsoleからBackend environmentsの初期化を行います。~~
Backend environmentsの`Get started`から行こうと思いましたが、後述の`amplify pull`がうまく通らないため、`amplify init`で初期化を行うことにします。

プロジェクトのルートフォルダで`amplify init --appId <アプリケーションID>`を実行します。
質問には適切に答えてください。今回はすべてデフォルトで行っています。

```console
amplify init --appId d1rjrcnv3buqsn
Note: It is recommended to run this command from the root of your app directory
? Enter a name for the project amplifyreact
? Enter a name for the environment dev
? Choose your default editor: Visual Studio Code
? Choose the type of app that you're building javascript
Please tell us about your project
? What javascript framework are you using react
? Source Directory Path:  src
? Distribution Directory Path: build
? Build Command:  npm.cmd run-script build  
? Start Command: npm.cmd run-script start
Using default provider  awscloudformation
```

## 認証機能の設定（バックエンド）
AmplifyのアプリケーションからAdmin UIを開きます。
Backend environmentsに、`amplify init`で作成されたenvironmentがあるので、そこの`Open admin UI`をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/556091/efbb1d35-8fd2-a4e7-7043-732571eda937.png)

左側のナビゲーションバーの`Authentication`を選択し、必要な設定を行い`Save and deploy`をクリックします。
ここでGoogleやFacebookとのフェデレーションも行えるのですが、今回はシンプルにメールアドレスの認証だけとします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/556091/4f50a44d-8b21-ad32-588c-ec3a111fc871.png)

画面が切り替わるので、右上の`Deploying...`が切り替わるまで待ちます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/556091/fc91ede9-8036-3ed8-ec75-d3d60febe56a.png)

画面が切り替わると、Amplify CLIで使用するコマンドが表示されますので、コピーします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/556091/9d316a79-30e9-425b-9dcc-aad0e225bbe0.png)![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/556091/08066f29-87cf-7fa9-17f9-86cdc68bb1b5.png)

プロジェクトのルートフォルダで、先程のコマンドを実行します。

```console
amplify pull --appId d1rjrcnv3buqsn --envName dev
```

# フロントエンドの設定
aws-amplifyと@aws-amplify/ui-reactをインストールします。

```console
npm install aws-amplify @aws-amplify/ui-react
```

index.jsおよびApp.jsを下記のように修正します。

```diff_jsx:index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
+ import Amplify from 'aws-amplify';
+ import config from './aws-exports';
+ Amplify.configure(config);

ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  document.getElementById('root')
);

// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();
```

```diff_jsx:App.js
import logo from './logo.svg';
import './App.css';
+ import { withAuthenticator, AmplifySignOut } from '@aws-amplify/ui-react'

function App() {
  return (
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <p>
          Hello World!!
        </p>
        <a
          className="App-link"
          href="https://reactjs.org"
          target="_blank"
          rel="noopener noreferrer"
        >
          Learn React
        </a>
      </header>
+       <AmplifySignOut />
    </div>
  );
}

+ export default withAuthenticator(App);
- export default App;
```

上記で`npm start`を行うと、サインイン画面が表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/556091/5508ccd5-5341-0d9a-1a70-4d9d9fa95658.png)

Create accountからユーザー作成を行い、サインインを行うと画面の下部にサインアウトボタンが追加されており、クリックすることでサインイン画面に戻ることが確認できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/556091/824a1939-c43a-0ec2-63ab-62c47bb3150f.png)

# GitHubリポジトリへの適用
これをGitHubリポジトリにpushすることで、Amplifyがホストしているアプリケーションも自動でデプロイされるのですが、デフォルトではなぜか`aws-exports.js`がgitignoreで追跡対象外になっているので、コメントアウトしておきます。
`index.js`でimportしているため、GitHubにアップロードしないと、ビルドエラーになります。

```:gitignore
#amplify
amplify/\#current-cloud-backend
amplify/.config/local-*
amplify/mock-data
amplify/backend/amplify-meta.json
amplify/backend/awscloudformation
build/
dist/
node_modules/
#aws-exports.js <- コメントアウト
awsconfiguration.json
amplifyconfiguration.json
amplify-build-config.json
amplify-gradle-config.json
amplifytools.xcconfig
```