Quasar Cognito Step 3: Initialize Authentication and Secure the Vue Router

·

6 min read

This is part 3 in a series of posts from Add User Authentication to Quasar with AWS Cognito in 5 simple steps. We will be covering the steps it takes to use AWS Amplify to configure and connect to Cognito as well as how to secure the Vue Router.

Initialize Authentication on Boot

Quasar allows you to run code before the root Vue app instance has been instantiated through boot files. This is how we will initialize Cognito and connect it to the Vue Router.

Install Dependencies and Create the Necessary Files

  • From a terminal, navigate to the root of your project
    • Cmder is great if you are using Windows
  • Open the project in your favorite code editor (VSCode is the best)
    • code .
  • Go back to the terminal
  • Install @aws-amplify/auth
    • We only need the auth functions from Amplify
    • npm install @aws-amplify/auth --save
  • Create a new boot file
    • quasar new boot auth
  • Create a new folder named auth
    • cd src/boot && mkdir auth
  • Create a new file in the auth directory for Cognito config
    • touch cognitoConfig.js

Cognito Config

  • Here is the completed config file with optional parameters commented out
  • Switch to your code editor and open src/boot/auth/cognitoConfig.js
  • You only need to setup three parameters. The values can be found in the AWS console
    • See Create a Cognito User Pool for more information
    • Region
      • The region will be the first part of the User Pool ID
      • For example: us-west-2
    • User Pool ID
      • image.png
    • User Pool Web Client ID (26-char alphanumeric string)
      • image.png

const cognitoConfig = {
  Auth: {

    // REQUIRED - Amazon Cognito Region
    region: 'us-west-2',

    // Amazon Cognito User Pool ID
    userPoolId: '',

    // Amazon Cognito Web Client ID (26-char alphanumeric string)
    userPoolWebClientId: ''
  }
}

export { cognitoConfig }

Boot File

  • Here is the completed boot file: auth.js
  • Open src/boot/auth.js in your code editor
  • Import the dependencies and initialize Amplify
    • Notify is used to let the user know they do not have access to a page
import { Auth } from '@aws-amplify/auth'
import { cognitoConfig } from './auth/cognitoConfig'
Auth.configure(cognitoConfig)

import { Notify } from 'quasar'
  • Create a function to route and notify the user when they navigate to a page without signing in

function goToSignUp (next) {
  Notify.create({
    message: 'You need to sign in to view this page',
    type: 'negative'
  })
  next('/auth/signup')
}
  • Create the Export Default for the Boot file
    • The next two steps will be placed inside here
export default async ({ app, router, store, Vue }) => {
  // More to come in here...
}
  • Setup Amplify as a plugin so we can call it globally using this.$Auth
  // Put this inside the Export Default
  const plugin = {
    install () {
      Vue.Auth = Auth
      Vue.prototype.$Auth = Auth
    }
  }
  Vue.use(plugin)
  • The next section uses the Vue Router's beforeEach function to check for routes that need authentication
    • The requiresAuth meta value is setup in the Vue Router which will be explained after this section
    • To check if a user is signed in we call Auth.currentAuthenticatedUser()
// This also goes into the Export Default
  router.beforeEach(async (to, from, next) => {
    if (to.matched.some(record => record.meta.requiresAuth)) {
      try {
        const isSignedIn = await Auth.currentAuthenticatedUser()
        if (isSignedIn) {
          next()
        } else {
          goToSignUp(next)
        }
      } catch (error) {
        if (error === 'not authenticated') {
          goToSignUp(next)
        } else {
          throw error
        }
      }
    } else {
      next()
    }
  })

Vue Router

  • Here is the completed routes.js file
  • The Vue Router has a meta section that contains the attribute requiresAuth: true for any page that needs to be secure
    • This is setup in the src/router/routes.js meta section of a route
...

  {
    path: '/',
    component: () => import('layouts/MainLayout.vue'),
    children: [
      { path: '/userprofile', component: () => import('pages/UserProfile.vue'), name: 'UserProfile' }
    ],
    meta: {
      requiresAuth: true
    }
  },

...