DEV Community

Cover image for Using AWS Cognito with Vue/NuxtJS
Pieter van der Westhuizen
Pieter van der Westhuizen

Posted on

Using AWS Cognito with Vue/NuxtJS

In my last post, "Using AWS Cognito with Xamarin Forms", I showed how to authenticate with Amazon Cognito using Xamarin Forms and the Xamarin.Essentials Web Authenticator.

In this post, we'll go through the process of using the AWS Cognito Hosted UI with your own Vue/NuxtJS site. For an idea on the final result, please take a look at the video below.

Setting up an AWS Cognito user pool

We'll be using the same AWS Cognito User pool and App client that we've created in my previous post. Please refer to the instructions details therein.

Creating the Vue/Nuxt project

To create the Nuxt project, open up your preferred terminal window and enter the following command:

yarn create nuxt-app mynuxtapp
Enter fullscreen mode Exit fullscreen mode

When prompted, you can select the following options:

  1. Project name: mynuxtapp
  2. Programming language: JavaScript
  3. Package manager: Yarn
  4. UI framework: Vuetify.js
  5. Nuxt.js modules: Axios
  6. Rendering mode: Single Page App
  7. Deployment target: Static (Static/Jamstack hosting)

I've assumed you've already installed everything necessary to create Vue/Nuxt projects. If not, please refer to the NuxtJS documentation

Adding the nuxt/auth dependency

Add the nuxt/auth dependency to you project by executing the following command:

yarn add --exact @nuxtjs/auth-next
Enter fullscreen mode Exit fullscreen mode

Next, in the nuxt.config.js file, add the nuxt/auth module to the modules array.

  modules: [
    "@nuxtjs/axios",
    "@nuxtjs/auth-next"
  ],
Enter fullscreen mode Exit fullscreen mode

While we have the nuxt.config.js file open, also add the auth section as below:

  auth: {
    strategies: {
      awsCognito: {
        scheme: "oauth2",
        endpoints: {
          authorization: "https://myxamarinapp.auth.us-east-1.amazoncognito.com/login",
          token: "https://myxamarinapp.auth.us-east-1.amazoncognito.com/oauth2/token",
          userInfo: "https://myxamarinapp.auth.us-east-1.amazoncognito.com/oauth2/userInfo",
          logout: "https://myxamarinapp.auth.us-east-1.amazoncognito.com/logout"
        },
        token: {
          property: "access_token",
          type: "Bearer",
          maxAge: 3600
        },
        refreshToken: {
          property: "refresh_token",
          maxAge: 60 * 60 * 24 * 30
        },
        responseType: "token",
        redirectUri: "http://localhost:3000/login",
        logoutRedirectUri: "http://localhost:3000/login",
        clientId: "4jlfe2iki0ucn32uc44clmib3d",
        scope: ["email", "openid", "profile"],
        codeChallengeMethod: "S256"
      }
    }
  }
Enter fullscreen mode Exit fullscreen mode

We're using the built-in OAuth2 scheme and we're calling it awsCognito. The endpoints are:

authorization
This is the domain/url we've configured in AWS Cognito with /login appended. This loads the login page.

token
This is the domain/url we've configured in AWS Cognito with /oauth2/token appended. This endpoint is used to get the user's tokens.

userInfo
This is the domain/url we've configured in AWS Cognito with /oauth2/userInfo appended. This endpoint is used to retrieve information about the authenticated user.

logout
This is the domain/url we've configured in AWS Cognito with /logout appended. Used to sign the user out.

For more detail regarding these endpoints, please refer to the Amazon Cognito user pools Auth API Reference

The rest of the auth options should be relatively self-explanatory. For this example the important config entries are:

response_type
Set this to token to inform AWS Cognito that we want an access_token back.

redirectUri
This value should also be added to the list of Callback URL(s) under App integration > App client settings in AWS Cognito.
image

clientId
Is the same Client Id as configured in AWS Cognito. You'll find this under General settings > App clients
image

codeChallengeMethod
Amazon Cognito authentication server only support S256. This value must be supplied for the nuxt/auth OAuth scheme to work or else you'll receive a "unsupported code challenge method" error.

The last change we need to make in the nuxt.config.js file is to enable the auth middleware globally. Do this by setting the router middleware, as show below:

 router: {
    middleware: ["auth"]
  }
Enter fullscreen mode Exit fullscreen mode

UI Changes

Login Page
We'll add a simple login page, inside the pages folder, called login.vue. The page will prompt the user to log in if they are not authenticated. I contains a simple login method that logs in using the awsCognito scheme we've configured in the previous step, the code for the method follows:

methods: {
    login() {
      this.$auth.loginWith("awsCognito");
    }
  }
Enter fullscreen mode Exit fullscreen mode

The full code listing for the login page are:

<template>
  <v-row align="center" justify="center">
    <v-col cols="12" sm="8" md="4">
      <v-card class="elevation-12" v-if="loggedIn">
        <v-card-title>Logging in.</v-card-title>
        <v-card-text
          >Logging in, please wait...
          <v-progress-circular indeterminate color="green"></v-progress-circular>
        </v-card-text>
      </v-card>
      <v-card class="elevation-12" v-else>
        <v-card-title>You're not logged in</v-card-title>
        <v-card-text>Click the button to log into your account. </v-card-text>
        <v-card-actions>
          <v-btn @click="login" color="primary">Login</v-btn>
        </v-card-actions>
      </v-card>
    </v-col>
  </v-row>
</template>

<script>
export default {
  layout: "unauthorized",
  data() {
    return {
      loggedIn: false
    };
  },
  created() {
    this.loggedIn = this.$auth.strategy.token.get();
  },
  methods: {
    login() {
      this.$auth.loginWith("awsCognito");
    }
  }
};
</script>

Enter fullscreen mode Exit fullscreen mode

In the page template we use v-if and v-else directives to either show a login button or a message informing the user that they are being logged in. This is useful when AWS Cognito redirects to the login page after the user has logged in.

Home Page
The home page is located in the pages/index.vue file. This file should've been automatically added for you when you've created the project. This page will only be shown once the user is authenticated and will display some of the user's information as illustrated in the following image:
image

There is not much logic in the page. The most important aspects is that we show the user information using properties on the this.$auth.user object and the logOut method uses this.$auth.logout() to log the user out when the "Log Out" button is clicked.

The full code listing for the page follows:

<template>
  <v-row justify="center" align="center">
    <v-col cols="12" sm="8" md="6">
      <div class="text-center">
        <logo />
        <vuetify-logo />
      </div>
      <v-card>
        <v-card-title class="headline"> Welcome {{ username }}, you are logged in! </v-card-title>
        <v-card-text>
          <p>
            Here are your user details, retrieved from the
            <a href="https://docs.aws.amazon.com/cognito/latest/developerguide/userinfo-endpoint.html">/USERINFO</a>
            endpoint:
          </p>
          <template>
            <v-simple-table>
              <template v-slot:default>
                <thead>
                  <tr>
                    <th class="text-left">
                      Property
                    </th>
                    <th class="text-left">
                      Value
                    </th>
                  </tr>
                </thead>
                <tbody>
                  <tr>
                    <td>Email</td>
                    <td>{{ email }}</td>
                  </tr>
                  <tr>
                    <td>Phone number</td>
                    <td>{{ phoneNumber }}</td>
                  </tr>
                  <tr>
                    <td>UserId/sub</td>
                    <td>{{ userId }}</td>
                  </tr>
                  <tr>
                    <td>User name</td>
                    <td>{{ username }}</td>
                  </tr>
                  <tr>
                    <td>Access Token</td>
                    <td>{{ accessToken }}</td>
                  </tr>
                  <tr>
                    <td>Refresh Token</td>
                    <td>{{ refreshToken }}</td>
                  </tr>
                </tbody>
              </template>
            </v-simple-table>
          </template>
        </v-card-text>
        <v-card-actions>
          <v-spacer />
          <v-btn color="primary" @click="logOut">
            Log Out
          </v-btn>
        </v-card-actions>
      </v-card>
    </v-col>
  </v-row>
</template>

<script>
import Logo from "~/components/Logo.vue";
import VuetifyLogo from "~/components/VuetifyLogo.vue";

export default {
  components: {
    Logo,
    VuetifyLogo
  },
  data() {
    return {
      email: null,
      phoneNumber: null,
      userId: null,
      username: null,
      accessToken: null,
      refreshToken: null
    };
  },
  created() {
    this.email = this.$auth.user.email;
    this.phoneNumber = this.$auth.user.phone_number;
    this.userId = this.$auth.user.sub;
    this.username = this.$auth.user.username;
    this.accessToken = this.$auth.strategy.token.get();
    this.refreshToken = this.$auth.strategy.refreshToken.get();
  },
  methods: {
    logOut() {
      this.$auth.logout();
    }
  }
};
</script>
Enter fullscreen mode Exit fullscreen mode

Note: I've explicitly shown on the page that the Refresh Token's value is false. This is because that AWS Cognito only returns refresh tokens if the Authorization Code grant is used. You can read more about refresh token in the Amazon Developer docs.

If everything goes according to plan, you should see a program flow similar to the video at the top of this post. I hope this post has been informative and that it can help you get started with Vue/Nuxt and Amazon Cognito.

Thank you for reading. Until next time, keep coding!

Full source code is available on GitHub: https://github.com/Pietervdw/vuenuxt-awscognito

Top comments (5)

Collapse
 
cissharp profile image
Pradip Shrestha

How can you login with facebook provider in cognito?

Collapse
 
pietervdw profile image
Pieter van der Westhuizen

Hi Pradip,

Funny enough, I'm currently busy with a client project that has Facebook integration :)

I'll see if I can get an opportunity to write a post on what you've mentioned.

Collapse
 
cissharp profile image
Pradip Shrestha

Hi Pieter,

Any update on the feature you are working on?

Thanks

Collapse
 
kwae profile image
Gage Keenan

I've noticed that the refresh token doesn't show on the table of data. Has anyone else noticed this too?

Collapse
 
pietervdw profile image
Pieter van der Westhuizen

Hi Gage,

Thank you for reading! I do make mention about this in the post. AWS Cognito only returns refresh tokens if the Authorization Code grant is used. Check out their docs for details about this: developer.amazon.com/docs/login-wi...