[ AWS Amplify + Vue.js ] Authでログイン画面作る

2020-12-02AWS Amplify,IT記事AWS Amplify,Vue.js

この記事では AWS Amplify の@aws-amplify/ui-vueを使用したログインフォームの作り方を解説します。

routerで認証を確認して、ログインが必要なページにアクセスするとSignInページに遷移する作りを目指します。

まず Amplify CLI が使えるようにはじめの設定を行ってください。チュートリアルへのリンク

次に vue プロジェクトを作成して移動します。

Vue Cliでプロジェクトを作成するときは vuex と router を含めるようにします。

vue create authlogin
cd authlogin

次にプロジェクトルートで、amplify init をしてAmplify の設定を行います。

amplify init

次に認証を追加します。

ampliy add auth で、amplify に認証を加えます。

設定時にサインインの認証にユーザー名ではなく Email を使うように設定します。

amplify add auth

 Do you want to use the default authentication and security configuration? Default configuration
 How do you want users to be able to sign in? Email
 Do you want to configure advanced settings? No, I am done.

Vue用のJSライブラリを npm install します。

npm install aws-amplify @aws-amplify/ui-vue

次にmain.jsにamplifyライブラリをインポートするコードを書きます。

import Vue from "vue";
import App from "./App.vue";
import router from "./router";
import store from "./store";

Vue.config.productionTip = false;

import Amplify from "aws-amplify";
import "@aws-amplify/ui-vue";
import aws_exports from "./aws-exports";

Amplify.configure(aws_exports);

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

routerでは、未認証ユーザーが認証の必要なページにアクセスした時と、ユーザーがログアウトボタンでログアウトした時に、サインインページへ自動で移動するようにします。

import Vue from "vue";
import VueRouter from "vue-router";
import Home from "../views/Home.vue";

import SignIn from "../components/SignIn.vue";

import { Hub } from "@aws-amplify/core";
import Auth from "@aws-amplify/auth";

import UserDataStore from "@/store/index";

Vue.use(VueRouter);

let user;

function getUser() {
  return Auth.currentAuthenticatedUser()
    .then((data) => {
      if (data && data.signInUserSession) {
        UserDataStore.commit("setUser", data);
        return data;
      }
    })
    .catch((e) => {
      console.error(e);
      UserDataStore.commit("setUser", null);
      return null;
    });
}

Hub.listen("auth", async (data) => {
  switch (data.payload.event) {
    case "signIn":
      user = await getUser();
      router.push({ path: "/" });
      break;
    case "signOut":
      user = null;
      UserDataStore.commit("setUser", null);
      router.push({ path: "/signin" });         // 1
      break;
  }
});

const routes = [
  {
    path: "/",
    name: "Home",
    component: Home,
    meta: { requiresAuth: true },
  },
  {
    path: "/signin",                          // 1
    name: "SignIn",
    component: SignIn,
    meta: { requiresAuth: false },
  },
];

const router = new VueRouter({
  mode: "history",
  base: process.env.BASE_URL,
  routes,
});

router.beforeResolve(async (to, from, next) => {
  if (to.matched.some((record) => record.meta.requiresAuth)) {
    user = await getUser();
    // console.log(user);
    if (!user) {
      return next({
        path: "/signin",                   // 1
        query: {
          redirect: to.fullPath,
        },
      });
    }
    return next();
  }
  return next();
});

export default router;

getUser という関数で、現在のユーザー情報をstoreに入れます。storeは後ほど書きます。

amplify-core の Hub というコンポーネントで、ユーザーがSignIn画面でログイン、ログアウトしたタイミングを検知してページ遷移を行うようにします。

(今回 /signin というパスでサインインするようにしています。アドレスを変える場合 1 の部分を変更してください。 )

user storは以下になります。

import Vue from "vue";
import Vuex from "vuex";

Vue.use(Vuex);

export default new Vuex.Store({
  state: {
    user: null,
  },
  mutations: {
    setUser(state, user) {
      state.user = user;
    },
  },
  getters: {
    isSignIn: (state) => {
      return state.user !== null;
    },
  },
  actions: {},
  modules: {},
});

最後にログインフォームが書かれている SignIn コンポーネントを書きます。

amplify-authenticator タグというのを使って、基本的なログインフォームを作成します。

以下の設定でメールアドレスと、パスワードの入力がある画面になります。

<template>
  <div class>
    <amplify-authenticator username-alias="email">
      <!-- The rest of your app code -->
      <amplify-sign-up slot="sign-up" username-alias="email" :form-fields.prop="formFields"></amplify-sign-up>
      <amplify-sign-out></amplify-sign-out>
    </amplify-authenticator>
  </div>
</template>

<script>
export default {
  data() {
    return {
      formFields: [
        {
          type: "email",
          label: "Email",
          placeholder: "",
          required: true
        },
        {
          type: "password",
          label: "Password",
          placeholder: "",
          required: true
        }
      ]
    };
  }
};
</script>

まとめ

ログイン用のルーティングと、amplifyに用意されているログインフォームを使用したログイン画面を作りました。