dayjournal memo

Total 975 articles!!

Try #067 – AWS AmplifyとAmplify UI VueとVue 3でログイン機能を構築してみた

Yasunori Kirimoto's avatar

画像




画像




AWS AmplifyとAmplify UI VueとVue 3でログイン機能を構築してみました!


以前の記事では、Vue.js v2用のAmplify UI Components「ui-vue」を利用していました。今回は、Vue 3の「ui-components」でログイン機能を構築してみました。



事前準備


全体構成

バックエンド - ユーザー管理

  • Amazon Cognito

フロントエンド - ログイン機能

  • AWS Amplify
  • Vue.js v3


バックエンド


まずは、バックエンドを構築していきます。
AWS Amplify #003 - 認証機能を追加


認証機能のみであればこの2コマンドで実装可能です!

amplify add auth

amplify push

これでバックエンドの構築は完了になります。



フロントエンド


次に、フロントエンドを構築していきます。


実行環境

  • node v16.10.0
  • npm v7.24.0

まず、プロジェクトに必要なパッケージを2つインストールします。

npm install aws-amplify

npm install @aws-amplify/ui-components


最後に、実際にログイン機能のコードを記述していきます。

基本的には、routerに認証部分のコードを記述し、UIは既にあるコンポーネントを指定することでそのまま表示することが可能です。


全体構成

画像


package.json

{
  "name": "amplify-geo",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "serve": "vue-cli-service serve",
    "build": "vue-cli-service build",
    "lint": "vue-cli-service lint"
  },
  "dependencies": {
    "@aws-amplify/ui-components": "^1.9.2",
    "aws-amplify": "^4.3.4",
    "core-js": "^3.6.5",
    "vue": "^3.0.0",
    "vue-router": "^4.0.0-0",
    "vuex": "^4.0.0-0"
  },
  "devDependencies": {
    "@vue/cli-plugin-babel": "~4.5.0",
    "@vue/cli-plugin-eslint": "~4.5.0",
    "@vue/cli-plugin-router": "~4.5.0",
    "@vue/cli-plugin-vuex": "~4.5.0",
    "@vue/cli-service": "~4.5.0",
    "@vue/compiler-sfc": "^3.0.0",
    "babel-eslint": "^10.1.0",
    "eslint": "^6.7.2",
    "eslint-plugin-vue": "^7.0.0"
  },
  "eslintConfig": {
    "root": true,
    "env": {
      "node": true
    },
    "extends": [
      "plugin:vue/vue3-essential",
      "eslint:recommended"
    ],
    "parserOptions": {
      "parser": "babel-eslint"
    },
    "rules": {}
  },
  "browserslist": [
    "> 1%",
    "last 2 versions",
    "not dead"
  ]
}


/src


main.js

import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'

import {
  applyPolyfills,
  defineCustomElements
} from '@aws-amplify/ui-components/loader';
import Amplify from 'aws-amplify';
import awsconfig from './aws-exports';
Amplify.configure(awsconfig);

applyPolyfills().then(() => {
  defineCustomElements(window);
});

const app = createApp(App);
app.config.isCustomElement = tag => tag.startsWith('amplify-');
app.use(store).use(router).mount('#app');


/src/store


index.js

import { createStore } from 'vuex'

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


/src/router


index.js

import { createRouter, createWebHistory } from 'vue-router'
import Home from '../views/Home.vue'
import Login from '../components/Login.vue'
import store from '../store/index.js'
import { Hub } from "@aws-amplify/core"
import Auth from "@aws-amplify/auth"

let user;

getUser().then((user) => {
    if (user) {
        router.push({path: '/'});
    }
});

function getUser() {
    return Auth.currentAuthenticatedUser().then((data) => {
        if (data && data.signInUserSession) {
            store.commit('setUser', data);
            return data;
        }
    }).catch(() => {
        store.commit('setUser', null);
        return null;
    });
}

Hub.listen("auth", async (data) => {
    if (data.payload.event === 'signOut'){
        user = null;
        store.commit('setUser', null);
        router.push({path: '/login'});
    } else if (data.payload.event === 'signIn') {
        user = await getUser();
        router.push({path: '/'});
    }
});

const routes = [
        {
            path: '/login',
            name: 'login',
            component: Login
        },
        {
            path: '/',
            name: 'home',
            component: Home,
            meta: { requiresAuth: true}
        }
]

const router = createRouter({
  history: createWebHistory(process.env.BASE_URL),
  routes
})

router.beforeResolve(async (to, from, next) => {
    if (to.matched.some(record => record.meta.requiresAuth)) {
        user = await getUser();
        if (!user) {
            return next({
                path: '/login'
            });
        }
        return next()
    }
    return next()
});

export default router


/src/views


Home.vue

<template>
  <div class="home">
    <img alt="Vue logo" src="../assets/logo.png">
    <amplify-sign-out></amplify-sign-out>
  </div>
</template>

<script>
export default {
  name: 'Home',
  components: {
  }
}
</script>


/src/components


Login.vue

<template>
    <div class="login">
        <amplify-authenticator></amplify-authenticator>
    </div>
</template>

<script>
    export default {
        name: 'login'
    }
</script>


簡易ローカルサーバーで確認

npm run serve


ローカルサーバーを立ち上げて、ログイン画面でユーザーを登録しログインしてみます。

画像



AWSのコンソールを確認するとユーザーも正常に登録さています。

画像




AWS AmplifyとAmplify UI VueとVue 3を利用することで、手軽にログイン機能の構築ができました!

AWS Amplify CLIが登場したことにより、Amplifyを利用する場合に以前よりサーバーレス設定周りがめちゃくちゃ便利になったのでおすすめです。



AWS AmplifyとVue.jsについて、他にも記事を書いています。よろしければぜひ。
tags - AWS Amplify
tags - Vue.js



book

Q&A