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 • Edited on

5 2

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!

Image of Timescale

🚀 pgai Vectorizer: SQLAlchemy and LiteLLM Make Vector Search Simple

We built pgai Vectorizer to simplify embedding management for AI applications—without needing a separate database or complex infrastructure. Since launch, developers have created over 3,000 vectorizers on Timescale Cloud, with many more self-hosted.

Read full post →

Top 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...

Best Practices for Running  Container WordPress on AWS (ECS, EFS, RDS, ELB) using CDK cover image

Best Practices for Running Container WordPress on AWS (ECS, EFS, RDS, ELB) using CDK

This post discusses the process of migrating a growing WordPress eShop business to AWS using AWS CDK for an easily scalable, high availability architecture. The detailed structure encompasses several pillars: Compute, Storage, Database, Cache, CDN, DNS, Security, and Backup.

Read full post