SANDFISH FACTORY

技術ブログです。python・vuejsを愛でる日々について綴ります

Vue.jsとAWS Amplifyで開発するサーバレスなWebアプリ:authコンポーネント

はじめに

前回の投稿でAWS Amplifyを利用したVue.jsの開発環境を構築しました。
今回はAWS Amplifyのauthを少し掘り下げます。 authを利用できれば認証を簡単に組み込むことができます。

authコンポーネント

aws-amplify-vueにはいくつかのコンポーネントが用意されています。
前回の投稿では amplify-authenticator amplify-sign-out を利用しました。

amplify-authenticator

概要

amplify-authenticatorは認証に関する機能が用意されています。
このコンポーネントを呼び出すだけで一通りのことが実現できます。含まれているのは以下の機能です。

  • サインアップ
  • サインアップ確認
  • サインイン確認
  • サインイン
  • パスワード再設定
<template>
    <amplify-authenticator :auth-config="authConfig" />
</template>

<script>
import { AmplifyEventBus } from 'aws-amplify-vue'
import Auth from '@aws-amplify/auth'

export default {
  props: [],
  data () {
    return {
      authConfig: {
        signInConfig: {
          header: 'サインイン'
        },
        signUpConfig: {
          hideDefaults: true,
          signUpFields: [
            { label: 'ユーザーID', key: 'username', required: true, type: 'email', displayOrder: 0 },
            { label: 'パスワード', key: 'password', required: true, type: 'password', displayOrder: 1 }
          ]
        },
        confirmSignUpConfig: {},
        forgotPasswordConfig: {},
        confirmSignInConfig: {}
      }
    }
  }
}
</script>

signUpConfig、signInConfigなどが各コンポーネントの設定情報です。
signUpConfigのsignUpFieldsにはサインアップ画面のフィールドを定義しています。

  • label:フィールドのラベル
  • key:フィールドの値とcognitoの属性値を紐づけています。
  • required:必須か
  • type:フィールドタイプ(type: 'text'とするとただのテキストフィールドになります)
  • displayOrder:フィールドの表示順

詳しいドキュメントはこちらを参照してください。

イベント

コンポーネントで発生するイベントはAmplifyEventBus経由で受け取ります。 リスナーを登録して適宜必要な処理を実装します。

AmplifyEventBus.$emit('authState', 'signedIn') はユーザーがサインインに成功したときに発生します。

前回のサンプルプログラムで実装したのは

  • beforeCreateフック内でユーザー情報を取得する。
  • 取得したユーザーのauthStateの値で処理を振り分ける
  • signedInなら/photoへ移動する。
import { AmplifyEventBus } from 'aws-amplify-vue'
import Auth from '@aws-amplify/auth'

export default {
  props: [],
  data () {
    return {
      signedIn: false,
  // 〜 省略 〜
  },
  async beforeCreate () {
    try {
      await Auth.currentAuthenticatedUser()
      this.signedIn = true
    } catch (err) {
      console.log(err)
      this.signedIn = false
    }
    AmplifyEventBus.$on('authState', (info) => {
      if (info === 'signedIn') {
        this.signedIn = true
        this.$router.push('/photo')
      } else {
        this.signedIn = false
      }
    })
  }
}

amplify-sign-out

概要

amplify-sign-out はサインアウトする機能が用意されています。

<template>
    <amplify-sign-out />
</template>

<script>
import { AmplifyEventBus } from 'aws-amplify-vue'
import Auth from '@aws-amplify/auth'

export default {
  props: [],
  data () {
    // 〜 省略 〜
  }
}
</script>

イベント

amplify-authenticatorと同様にAmplifyEventBus経由で受け取ります。

AmplifyEventBus.$emit('authState', 'signedOut') はユーザーがサインアウトに成功したときに発生します。

コンポーネントのUIカスタマイズ

英語のメッセージを日本語に変える

AWS Amplify I18nモジュールがあるため、そちらを使うことでメッセージを変更できます。

signOutButton: this.$Amplify.I18n.get('Sign Out')

コンポーネント内で指定されたキーでメッセージを取得しているので、日本語用のメッセージを登録することでメッセージを日本語に変えられます。

amplify-sign-up

  • signUpFields.label
    • 説明:フィールドのラベル、プレースホルダ
    • 備考:signUpFieldsのlabelをキーとして利用しています
  • 'Create Account'
    • 説明:アカウント作成ボタン
  • 'Have an account? '
    • 説明:アカウントはありますか?のラベル
  • 'Sign in'
  • 'Create a new account'
    • 説明:サインアップ画面ヘッダー
    • 備考:デフォルト値

amplify-sign-in

  • 'Password'
    • 説明:パスワード入力フィールドのラベル
  • 'Enter your password'
  • 'Forget your password? '
    • 説明:パスワード再設定リンクのヒント
  • 'Reset password'
    • 説明:パスワード再設定リンク
  • 'Sign In'
    • 説明:サインインボタンのテキスト
  • 'No account? '
  • 'Create account'
  • 'Sign in to your account'
    • 説明:サインイン画面ヘッダー
    • 備考:デフォルト値

amplify-confirm-sign-up

  • 'Confirmation Code'
    • 説明:確認コード入力のラベル
  • 'Lost your code? '
    • 説明:コード再送リンクのヒント
  • 'Resend Code'
    • 説明:コード再送リンクのテキスト
  • 'Confirm'
    • 説明:確認ボタンのテキスト
  • 'Have an account? '
    • 説明:アカウントはありますか?のラベル
  • 'Back to Sign In'
    • 説明:サインインに戻るリンクのテキスト
  • 'Confirm Sign Up'
    • 説明:サインアップ確認画面のヘッダー

amplify-sign-out

  • 'Sign Out'
    • 説明:サインアウトボタンのテキスト
    • 備考:デフォルト値

これらのメッセージをmain.jsに設定する。

import Vue from 'vue'
import './plugins/vuetify'
import App from './App.vue'
import router from './router'
import store from './store'
import Amplify, * as AmplifyModules from 'aws-amplify'
import { AmplifyPlugin } from 'aws-amplify-vue'
import awsconfig from './aws-exports'
Amplify.configure(awsconfig)

Vue.use(AmplifyPlugin, AmplifyModules)

Vue.config.productionTip = false
let messageResource = {
    ja:{
        'Create Account': '',
        'Have an account? ': '',
        'Sign in': '',
        'Create a new account': '',
        'Password': '',
        'Enter your password': '',
        'Forget your password? ': '',
        'Reset password': '',
        'No account? ': '',
        'Create account': '',
        'Sign in to your account': '',
        'Sign Out': ''
    }
}
AmplifyModules.I18n.putVocabularies(messageResource)

new Vue({
  router,
  store,
  render: h => h(App)
}).$mount('#app')

フィールドを追加する

サインアップ画面の入力フィールドにユーザ名とパスワード以外のフィールドを追加したいケースはあると思います。
signUpConfigのsignUpFieldsをカスタマイズすることで実現可能です。また、カスタム属性を追加することも可能です。

今回の例はカスタム属性を追加したケースです。 但し、issueに書いてありますが、今のamplify-cliでCognitoのカスタム属性の追加はできません。
ここだけ手作業が発生してしまいます。

amplify add auth
amplify push
  • pushしたのち、AWSのコンソールからCognitoの画面を開きます。
  • ユーザープールの画面を開きます。
    f:id:sandfish03:20190720144012p:plain
    属性値の設定(変更前)
  • カスタム属性としてtenantIdを追加します。
    f:id:sandfish03:20190720144406p:plain
    カスタム属性の追加
  • 変更を保存します。カスタム属性に tenantId が追加されました。

    f:id:sandfish03:20190720144536p:plain
    属性値の設定(変更後)

  • signUpFieldにテナントIDを追加します。

signUpConfig: {
  signUpFields: [
    { label: 'ユーザーID', key: 'username', required: true, type: 'email', displayOrder: 1 },
    { label: 'パスワード', key: 'password', required: true, type: 'password', displayOrder: 2 }
    { label: 'テナントID', key: 'custom:tenantId', required: true, type: 'text', displayOrder: 0 }
  ]
}
  • 起動してサインアップ画面に移動するとテナントIDが入力フィールドとして追加されていることが確認できます。

    f:id:sandfish03:20190721090044p:plain
    サインアップ画面(変更後)

  • サインアップしてユーザーを登録するときちんとカスタム属性に値が設定されています。

    f:id:sandfish03:20190720145950p:plain
    ユーザー情報(一部)

一部手作業が発生しますが、登録するユーザー情報にカスタム属性まで追加できることが確認できました。

まとめ

簡単なカスタマイズであれば可能ですが、全てが完璧という状態ではありませんでした。
自由度の高いカスタマイズを行うのであれば、自作のコンポーネントAWS AmplifyのAPIを用いて制御する必要がありそうです。

ちなみにコンポーネントに対する要望や課題(UIだけに限らず)を受けてリファクタリングを検討しているようで、Issueはこちらです。2019年末にはリリースしたいようです。

次回はstorageコンポーネントについて試したいと思います。