AWS Amplify の Authでログイン画面作る

AWS Amplify, IT記事

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

なので前回のコードを更新。

amplify add authで、Cognitoユーザープールを使うようにして、ログインにメールアドレスを使うように設定したあとから。

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では前回インポートしたりするコードがあったのですがなくなりました。あと、authのログイン挙動を取るのにHubというコンポーネントを使っています。

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

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

Vue.use(VueRouter);

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" });
      break;
  }
});

const routes = [
  {
    path: "/",
    name: "Home",
    component: Home,
    meta: { requiresAuth: true },
  },
  {
    path: "/signin",
    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",
        query: {
          redirect: to.fullPath,
        },
      });
    }
    return next();
  }
  return next();
});

export default router;

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) => {
      // console.log(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>

コードがシンプルになりましたね。以上です。