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

AWS Amplify, IT記事

この記事では AWS Amplify と Vue.js を使用したログイン用のルーティングと、ログインフォームの作り方を解説します。

前にも認証画面の記事を書いたのですが、その時は、aws-amplify-vue というライブラリを使いました。しかしこのライブラリはインポートの形とかコンポーネント性が悪かったそうで、今はチュートリアルでも @aws-amplify/ui-vueというライブラリを使うようになっています。

なので、前回の記事を書き直したのが今回の記事です。

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

次に vue プロジェクトを作成して移動します。作成するときは 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.

npm install します。以下のライブラリになります。

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

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

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に入れます。

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

今回 /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に用意されているログインフォームを使用したログイン画面を作りました。