Amplify + Nuxt.js + Cognitoでログイン機能を実装してみた

今回の記事は、AWS amplifyの機能の一つであるAuthenticationについての記事です。
Nuxt.jsとAmazon Cognitoによるアプリケーションにユーザーのサインアップ、サインインなどの機能を追加し、実際にログイン画面を実装していきたいと思います。

#環境
・Pug を使用
・コーディング規約は Nuxt.js に則って StandardJS
・Visual Studio Code 
※`amplify init`によりプロジェクトが初期化されている前提のもと話を進めていきます。

# Cognitoの準備
Cognitoを使用するためにAWSサービス機能のauthを追加しましょう

```shell:shell
$ amplify add auth

$ amplify push
```

# ライブラリの追加
Amplifyライブラリのインストールをします

```shell:shell
$ npm install aws-amplify --save
```

# ログイン画面の実装

## Amplifyライブラリを使えるようにする
まずはAmplifyをVueで使うための設定をします。`plugins`フォルダに`amplify.js`を作り以下のようにします

```javascript:amplify-vue.js
import Vue from 'vue'
import * as AmplifyModules from 'aws-amplify'
import { AmplifyPlugin } from 'aws-amplify-vue'
import awsconfig from '@/aws-exports'
Amplify.configure(awsconfig)

Vue.use(AmplifyPlugin, AmplifyModules)
```

## middlewareでのログイン判定

ユーザーからのログインが確認できない場合の制御を書きます
`middleware`のフォルダ内に`auth.js`を作り、以下のようにします。

```javascript:auth.js
import { Auth } from 'aws-amplify'

export default async ({ redirect }) => {
  const userInfo = await Auth.currentUserInfo()

  if (!userInfo) {
    redirect('/signin')
  }
}

```
`currentUserInfo`メソッドは`Auth`からユーザー情報を取ってくるメソッドです。従ってログインのリクエストをユーザが送った際に、`userInfo`の中にユーザー情報が入っていないとサインインのページ(/`signin`)にリダイレクトされるようになっています

##ログイン機能

`pages`フォルダ内に`signin.vue`を作り以下のようにします

```javascript:signin.vue

<template lang="pug">
    amplify-sign-out(
      v-if="isLoggedIn"
    )
    amplify-authenticator(
      v-else
      :authConfig="authConfig"
    )
</template>

<script>
export default {
  data () {
    return {
      isLoggedIn: false,
      authConfig: {
        usernameAttributes: 'My user name',
        signUpConfig: {
          header: 'My Customized Sign Up!',
          hideAllDefaults: true,
          defaultCountryCode: '1',
          signUpFields: [
            {
              label: 'My user name',
              key: 'username',
              required: true,
              displayOrder: 1,
              type: 'string'
            },
            {
              label: 'Password',
              key: 'password',
              required: true,
              displayOrder: 2,
              type: 'password'
            },
            {
              label: 'Phone Number',
              key: 'phone_number',
              required: true,
              displayOrder: 3,
              type: 'string'
            }
          ]
        }
      }
    }
  },
  async mounted () {
    const currentUserInfo = await this.$Amplify.Auth.currentUserInfo()
    this.isLoggedIn = Boolean(currentUserInfo)

    }
  }
}
</script>
```

### authenticatorのコンポーネント

Amplifyライブラリにはユーザーログイン機能に関連するコンポーネントを用意してくれています
今回使うのは`amplify-authenticator`と`amplify-signout`の2つです

####amplify-authenticator

このコンポーネントはサインアップ/サインインのフォームを用意してくれます。ユーザーがサインアップのフォームに登録情報を打ち込めば、Cognitoのユーザープールでユーザー情報を管理してくれます

サインイン画面
<img width="470" alt="スクリーンショット 2019-11-13 18.49.55.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/441587/e96c40ee-2d05-3329-d9e5-e77248c5c959.png">

サインアップ画面(サインイン画面のCreate accountを押すと表示が切り替わる)
<img width="507" alt="スクリーンショット 2019-11-13 23.14.54.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/441587/9c2fdef6-500f-135e-290a-989804215745.png">

サインアップの中身は簡単にカスタマイズすることができます。それは`data`の中にある`signUpConfig`で編集します

```javascript:script

  signUpConfig: {

          header: 'My Customized Sign Up!',
          hideAllDefaults: true,
          defaultCountryCode: '1',
          signUpFields: [
            {
              label: 'My user name',
              key: 'username',
              required: true,
              displayOrder: 1,
              type: 'string'
            },
            {
              label: 'Password',
              key: 'password',
              required: true,
              displayOrder: 2,
              type: 'password'
            },
            {
              label: 'Phone Number',
              key: 'phone_number',
              required: true,
              displayOrder: 3,
              type: 'string'
            }
          ]
        }
```

#### amplify-sign-out

サインアウトのボタンを表示してくれます。ボタンを押すとログイン画面に戻ります
<img width="404" alt="スクリーンショット 2019-11-13 23.31.41.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/441587/cf4caa52-d33b-9366-9110-c27b9dfaaf00.png">

### プログラムの流れ

手順を追って説明していきます。

#### 1　サインイン後

`async/await`を使い`$Amplify.Auth`に対し、`currentuserInfo()`メソッドにより、ユーザー情報を取得したのを確認したら、定数`currentuserInfo`に代入される

```javascript:script

const currentUserInfo = await this.$Amplify.Auth.currentUserInfo()

```
#### 2 Boolean値の切り替え

ユーザー情報が取得できている場合、サインアップとサインアウトの切り替えに用いる`isLoggedIn`のBoolean値を変更する

```javascript:script

this.isLoggedIn = Boolean(currentUserInfo)

```

#### 3　画面切り替え

v-ifによる条件分岐でサインアップorアウト画面の切り替えを行う

```javascript:signin.vue

amplify-sign-out(
      v-if="isLoggedIn"
    )
    amplify-authenticator(
      v-else
      :authConfig="authConfig"
    )

```

以上がAmlifyライブラリを使ったログイン機能の一連の流れです!
ちなみにサインアップされたユーザー情報はCognitoに以下のように管理されます
<img width="1088" alt="スクリーンショット 2019-11-14 0.11.15.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/441587/cdbe3ad1-82e2-06ec-196c-9b90a9477d48.png">

DBを使わずコンポーネント一つで登録、管理してくれるのはとても便利ですし、技術の進歩を実感しますね！
今後も最新技術について記事を書いていこうと思います！