DEV Community

Cover image for Building a Login Function with AWS Amplify, Amplify UI Vue, and Vue 3
Yasunori Kirimoto for AWS Community Builders

Posted on • Updated on

Building a Login Function with AWS Amplify, Amplify UI Vue, and Vue 3

img

I built a login function with AWS Amplify, Amplify UI Vue, and Vue 3 🎉

In my previous article, I used Amplify UI Components "ui-vue" for Vue.js v2. This time, I tried building a login function with Vue 3's "ui-components."

Advance Preparation

  • Build AWS Amplify and Vue 3 environment

AWS Amplify #002 - Building the environment

Overall composition

Backend - User Management

  • Amazon Cognito

Frontend - Login function

  • AWS Amplify
  • Vue.js v3

Backend

First, let's build the backend.

AWS Amplify #003 - Add Authentication Function

If you only need authentication, you can implement it with these two commands!

amplify add auth
Enter fullscreen mode Exit fullscreen mode
amplify push
Enter fullscreen mode Exit fullscreen mode

This completes the building of the backend.

Frontend

Next, let's build the front-end.

execution environment

  • node v16.10.0
  • npm v7.24.0

First, install the two packages required for the project.

npm install aws-amplify
Enter fullscreen mode Exit fullscreen mode
npm install @aws-amplify/ui-components
Enter fullscreen mode Exit fullscreen mode

Finally, write the actual code for the login function.

Write the code for the authentication part in the router, and the UI can be displayed as it is by specifying an already existing component.

Overall composition

img

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"
  ]
}
Enter fullscreen mode Exit fullscreen mode

/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');
Enter fullscreen mode Exit fullscreen mode

/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: {
  }
})
Enter fullscreen mode Exit fullscreen mode

/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
Enter fullscreen mode Exit fullscreen mode

/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>
Enter fullscreen mode Exit fullscreen mode

/src/components

Login.vue

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

<script>
    export default {
        name: 'login'
    }
</script>
Enter fullscreen mode Exit fullscreen mode

Let's check with a simple local server.

npm run serve
Enter fullscreen mode Exit fullscreen mode

Startup a local server, register a user on the login screen and try logging in.

img

If you check the AWS console, you can see that the user has been successfully registered.

img

By using an AWS Amplify, Amplify UI Vue, and Vue 3, we could quickly build a login function 👍

I recommend Amplify because the introduction of the AWS Amplify CLI makes the serverless configuration much more convenient than before!

Oldest comments (5)

Collapse
 
1nusah profile image
Inusah Said

Hi, how do you generate the aws-exports file?

Collapse
 
dayjournal profile image
Yasunori Kirimoto

Hi, Generated by "amplify init".
day-journal.com/memo/aws-amplify-002/

Collapse
 
1nusah profile image
Inusah Said

Thanks man, it was generated the whole time but i just wasn't seeing it. Really informative piece. Thanks

Collapse
 
wesleycheek profile image
Wesley Cheek

Thanks for this - it's a good minimum working example for the auth process.

Now I'm interested in implementing TOTP MFA - do you have any tips?

Collapse
 
dayjournal profile image
Yasunori Kirimoto

Hi, You may find this link helpful!
docs.amplify.aws/lib/auth/mfa/q/pl...