How to quickly authenticate a dashboard in Vue.js using Appwrite and Auth0

Amarachi Iheanacho - Jun 30 '22 - - Dev Community

In the age of large multi-user websites, it is essential to control what information a user has access to. This is achieved with authentication, a process which collects and identifies users who request access to an application or database.

What we are building

This article discusses authenticating, collecting, and displaying a piece of user information with Appwrite’s auth0 provider.

GitHub URL

https://github.com/Iheanacho-ai/auth0-authentication

Prerequisites

To get the most out of this project, the following are required:

  • A basic understanding of CSS, JavaScript, and Vue.js.
  • Docker Desktop installed on the computer; run the docker -v command to verify that we have Docker Desktop installed. If not, install it from the Get Docker documentation.
  • An Appwrite instance running on our computer. Check out this article to create a local Appwrite instance; we will use Appwrite’s robust database and Realtime service to manage our application.
  • An auth0 account; create a free account if you don’t have one.

Setting up our Vue.js application

We install the Vue CLI by running these terminal commands to create a new Vue project.

    npm install -g @vue/cli
    # OR
    yarn global add @vue/cli
Enter fullscreen mode Exit fullscreen mode

After installing the Vue CLI, we navigate to our preferred directory and create a new project.

    vue create <name of our project>
Enter fullscreen mode Exit fullscreen mode

We change the directory to the project and start a development server with:

    npm run serve
Enter fullscreen mode Exit fullscreen mode

To see the app, we go to http://localhost:8080/

Installing dependencies

Installing Tailwind CSS

Tailwind CSS is a "utility-first" CSS framework that allows us to create user interfaces for web applications rapidly.

To install Tailwind CSS in our project, we run the following terminal commands.

    npm install -D tailwindcss@latest postcss@latest autoprefixer@latest
    npx tailwindcss init -p
Enter fullscreen mode Exit fullscreen mode

These commands create two files in the root directory of our project, tailwind.config.js and postcss.config.js.

In our tailwind.config.js, we add the paths to all our template files with this code below.

    module.exports = {
      purge: ['./index.html', './src/**/*.{vue,js,ts,jsx,tsx}'],
      content: [],
      theme: {
        extend: {},
      },
      plugins: [],
    }
Enter fullscreen mode Exit fullscreen mode

Next, we add the tailwind directives in our src/index.css file.

    @tailwind base;
    @tailwind components;
    @tailwind utilities;
Enter fullscreen mode Exit fullscreen mode

Installing Vue router

Routing is the technology used to switch between different pages in our application based on the changes in the current URL.

We run this terminal command to enable our application to use Vue Router.

    npm install vue-router@4

    #or 

    yarn add vue-router@4   
Enter fullscreen mode Exit fullscreen mode

Installing Appwrite

Appwrite is an open-source, end-to-end, backend server solution that allows developers to build applications faster.

To use Appwrite in our Vue application, we install the Appwrite client-side SDK for web applications.

    npm install appwrite
Enter fullscreen mode Exit fullscreen mode

Creating a new Appwrite project

During the creation of the Appwrite instance, we specified what hostname and port we see in our console. The default value is localhost:80, so go to localhost:80 and create a new account to see our console.

From our console, click the Create Project button to start a new project.

Appwrite Console

Our project dashboard appears once we have created the project. At the top of the page, there is a Settings bar. Click it to access the Project ID and API Endpoint.

Appwrite Console

We copy the Project ID and API Endpoint, which we need to initialize the Appwrite Web SDK.

Appwrite Console

We create an init.js file at our project's root directory to initialize the Appwrite Web SDK with the following code.

    import { Appwrite } from 'appwrite';
    export const sdk = new Appwrite();
    sdk
      .setEndpoint('http://localhost/v1') // Replace this with your endpoint
      .setProject('projectID'); // Replace this with your ProjectID

Enter fullscreen mode Exit fullscreen mode

Enabling the auth0 provider in our application

In the Appwrite web Console, we click on Users on the left side of the dashboard to set up the auth0 provider for our application.

Appwrite Console

We go to the Settings tab to see the OAuth2 providers supported by Appwrite.

Appwrite Console

Appwrite Console

Creating an application on the auth0 dashboard

To enable us to use Appwrite’s auth0 provider, we create an application on the auth0 dashboard. Check out the auth0 documentation to understand how to create an auth0 application.

After creating our auth0 application, we click on the Settings tab to copy the Domain, Client ID, and Client Secret information of our auth0 application. We will use this information in our Appwrite console.

Appwrite Console

In our Appwrite console, we toggle the auth0 provider to open up the Auth0 OAuth2 settings.

Appwrite Console

Appwrite Console

Fill out the input fields with the information gathered from the auth0 dashboard.

Next, we copy the redirect URL on the Appwrite console and paste it into the Allowed Callback URLs input field on our auth0 dashboard.

Appwrite Console

Authenticating users in our application

Our application will contain two pages. The first page will authenticate and log in a user using the Appwrite auth0 provider, and the second page will display the user details.

Creating our login page

Our login page will consist of a button to allow users to log in via auth0.

We create a views folder for this user interface in our' src' folder. This src/views folder will contain a Home.vue file.

With this code, we create our login page in our src/views/Home.vue file.

    <template>
      <div class="login">
          <p>Click on this button to login</p>
          <button class= "button">Login with autho</button>
        </div>
    </template>
Enter fullscreen mode Exit fullscreen mode

Routing to our pages

In our src/main.js file, we enable our application to use router to navigate to different pages with this piece of code.

    import { createApp } from 'vue'
    import App from './App.vue'
    import router from './router'
    import './index.css';

    createApp(App).use(router).mount('#app')
Enter fullscreen mode Exit fullscreen mode

Next, we create a router folder in our src folder. Our router folder will contain an index.js file. This file will be responsible for defining what routes lead to specific components.

    // src/router/index.js
    import { createRouter,createWebHistory } from 'vue-router'
    import Home from '@/views/Home'
    import Notification from '@/views/Notifications'
    const routes = [
        {
            path: '/',
            name: 'Home',
            component: Home
        }
    ]
    const router = createRouter({
        history: createWebHistory(process.env.BASE_URL),
        routes
    })
    export default router;
Enter fullscreen mode Exit fullscreen mode

The code block above does the following:

  • Creates a routes array containing the route's path and the component we want the route to lead to.
  • Facilitates routing using the Vue createRouter method, which receives an object as a parameter. This object parameter has two fields, a history field and a route field, whose value is our route array.

Next, in our App.vue file, we add the router-view component and the CSS styles for the login page.

    <template>
      <div class="app-container">
        <router-view ></router-view>
       </div>
    </template>

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

    <style>
      .login{
        width: 450px;
        height: 150px;
        background: #fff;
        box-shadow: 0 10px 30px rgba(0,0,0,0.1);
        border-radius: 7px;
        margin: 10% auto;
        text-align: center;
        padding: 30px;
      }

      .button{
        width: 150px;
        height: 40px;
        background-color: #111;
        color: #fff;
        border-radius: 30px;
      }
    </style>

Enter fullscreen mode Exit fullscreen mode

The router-view component represents our component. In the code block above, we specify the position at which our app is situated.

To avoid errors resulting from non-multi-level component names, we replace our vue.config.js file with this code.

    const { defineConfig } = require('@vue/cli-service')
    module.exports = defineConfig({
      transpileDependencies: true,
      lintOnSave:false
    })
Enter fullscreen mode Exit fullscreen mode

Go to http://localhost:8080/ to see our Home page.

Appwrite Console

Creating the user profile page

In our src/views folder, we create a Dashboard.vue file to display the logged-in user profile.

    <template>
        <div class="user-details">
            <p><span>Name: </span></p>
            <p><span>Email: </span></p>
            <button class= "button">LogOut with Auth0</button>
        </div>
    </template>
Enter fullscreen mode Exit fullscreen mode

Next, we add the CSS styles for the user profile in the App.vue file.

    <style>
    .login, .user-details{
      width: 450px;
      height: 150px;
      background: #fff;
      box-shadow: 0 10px 30px rgba(0,0,0,0.1);
      border-radius: 7px;
      margin: 10% auto;
      text-align: center;
      padding: 30px;
    }

    .button{
      width: 150px;
      height: 40px;
      background-color: #111;
      color: #fff;
      border-radius: 30px;
    }

    span{
      font-weight: 600;

    }
    </style>
Enter fullscreen mode Exit fullscreen mode

We add a route to the routes object in the src/router/index.js file to view our Dashboard page in the browser.

   // src/router/index.js
   const routes = [
        {
            path: '/',
            name: 'Home',
            component: Home
        },
       {
            path: '/dashboard',
            name: 'Dashboard',
            component: Dashboard
        }
    ]
Enter fullscreen mode Exit fullscreen mode

Here is how our src/router/index.js file looks.

    import { createRouter,createWebHistory } from 'vue-router'
    import Home from '@/views/Home'
    import Dashboard from '@/views/Dashboard'
    const routes = [
        {
            path: '/',
            name: 'Home',
            component: Home
        },
        {
            path: '/dashboard',
            name: 'Dashboard',
            component: Dashboard
        }
    ]
    const router = createRouter({
        history: createWebHistory(process.env.BASE_URL),
        routes
    })
    export default router;
Enter fullscreen mode Exit fullscreen mode

To see our user profile page, go to http://localhost:8080/dashboard.

Appwrite Console

Authenticating a user with Appwrite’s auth0 provider

To allow a user to log in to their account using the auth0 provider, we write this piece of code in the Home.vue file of our project.

    <script>
    import {sdk} from '../../init';
      export default {
        name: 'Home',
        methods: {
          loginWithAutho: async function(){
            try {
              await sdk.account.createOAuth2Session('auth0', 'http://localhost:8080/dashboard', 'http://localhost:8080/error')
            } catch (error) {
              console.log(error)
            }
          }
        }
      };
    </script>
Enter fullscreen mode Exit fullscreen mode

We create an account session using the Appwrite createOAuth2Session method in the code block above. This createOAuth2Session method receives three parameters:

  • The OAuth2 provider we want to sign in a user with, which, in this example, is auth0.
  • The success argument is a redirect URL back to our app when the login is complete.
  • The failure argument is a redirect URL when the login fails.

Next, we pass the loginWithAutho method on the @click event listener on the Login with autho button.

    <button class= "button" @click="loginWithAutho">Login with autho</button>
Enter fullscreen mode Exit fullscreen mode

Here is how the Home.vue file looks.

    <template>
        <div class="login">
            <p>Click on this button to login</p>
            <button class= "button" @click="loginWithAutho">Login with autho</button>
          </div>
    </template>

    <script>
    import {sdk} from '../../init';
      export default {
        name: 'Home',
        methods: {
          loginWithAutho: async function(){
            try {
              await sdk.account.createOAuth2Session('auth0', 'http://localhost:8081/dashboard', 'http://localhost:8081/error')
            } catch (error) {
              console.log(error)
            }
          }
        }
      };
    </script>
Enter fullscreen mode Exit fullscreen mode

Displaying the stored user in our application

To display the user currently logged into our application, we write this code in the script section of our Dashboard.vue file.

    <script>
    import {sdk} from '../../init';
      export default {
        name: 'Dashboard',
        data(){
          return{
            namme: '',
            email: '',
            response: ''
          }
        },
        mounted: function(){
            this.getUserSession()
        },
        methods: {
          getUserSession: async function(){
            try {
              this.response = await sdk.account.get()
              if (this.response) {
                this.name = this.response.name,
                this.email = this.response.email 
              }

            } catch (error) {
              console.log(error)
            }
          },
          logOutWithAutho: async function(){
            try {
              await sdk.account.deleteSession('current')
              alert('logout successful')
              this.$router.push('/') 
            } catch (error) {
              console.log(error)
            }
          }
        }
      };

    </script>
Enter fullscreen mode Exit fullscreen mode

In the code block above, we do the following:

  • Create name, email, and response variables to hold a user's information.
  • Create a getUserSession function to fetch the current logged in user information. This getUserSession function updates the name, email, and response variable.
  • Use the mounted lifecycle hook to run the getUserSession function when the application mounts.
  • Create a logOutWithAutho function that logs a user out of our application by using the Appwrite deleteSession method. This logOutWithAutho function then navigates to our application’s home page.
  • Logs any error encountered during user logout.

In the Dashboard.vue file, we render the name and email variables. Next, we pass the logOutWithAutho function to the @click event listener on the LogOut with Auth0 button.

    <template>
      <div class="user-details">
        <p><span>Name: </span>{{name}}</p>
        <p><span>Email: </span>{{email}}</p>
        <button class= "button" @click="logOutWithAutho">LogOut with Auth0</button>
      </div>
    </template>
Enter fullscreen mode Exit fullscreen mode

Here is how our application looks.

Appwrite Console

Conclusion

This article discussed using Appwrite's OAuth2 auth0 provider to authenticate a user.

Resources

Here are some resources that might be helpful.

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .