Home » How to authenticate pages in Vuejs (OIDC)
what to do when nothing works out in life

How to authenticate pages in Vuejs (OIDC)

OpenID Connect (OIDC) is a widely-used authentication protocol on top of OAuth 2.0. There are several libraries available that make integrating OIDC into a Vue.js application relatively straightforward. One of the popular libraries for this purpose is @auth0/auth0-spa-js.

Below is a basic guide to setting up an OIDC client for Vue.js using @auth0/auth0-spa-js:

1. Install the necessary packages:

npm install @auth0/auth0-spa-js

2. Set up Auth0 configuration:

Create a new file named auth.js inside your src folder:

// src/auth.js

import Vue from 'vue';
import createAuth0Client from '@auth0/auth0-spa-js';

/** Define a default action to perform after authentication */
const DEFAULT_REDIRECT_CALLBACK = () =>
  window.history.replaceState({}, document.title, window.location.pathname);

let instance;

/** Returns the current instance of the SDK */
export const getInstance = () => instance;

/** Creates an instance of the Auth0 SDK. If one has already been created, it returns that instance */
export const useAuth0 = ({
  onRedirectCallback = DEFAULT_REDIRECT_CALLBACK,
  redirectUri = window.location.origin,
  ...options
}) => {
  if (instance) return instance;

  // The 'instance' is simply a Vue object
  instance = new Vue({
    data() {
      return {
        loading: true,
        isAuthenticated: false,
        user: {},
        auth0Client: null,
        popupOpen: false,
        error: null
      };
    },
    methods: {
      /** Authenticates the user using a popup window */
      async loginWithPopup(o) {
        this.popupOpen = true;

        try {
          await this.auth0Client.loginWithPopup(o);
          this.user = await this.auth0Client.getUser();
          this.isAuthenticated = true;
        } catch (e) {
          console.error(e);
        } finally {
          this.popupOpen = false;
        }
      },
      /** Handles the callback when logging in using a redirect */
      async handleRedirectCallback() {
        this.loading = true;
        try {
          await this.auth0Client.handleRedirectCallback();
          this.user = await this.auth0Client.getUser();
          this.isAuthenticated = true;
        } catch (e) {
          this.error = e;
        } finally {
          this.loading = false;
        }
      },
      /** Authenticates the user using the redirect method */
      loginWithRedirect(o) {
        return this.auth0Client.loginWithRedirect(o);
      },
      /** Returns all the claims present in the ID token */
      getIdTokenClaims(o) {
        return this.auth0Client.getIdTokenClaims(o);
      },
      /** Returns the access token. If the token is invalid or missing, a new one is retrieved */
      getTokenSilently(o) {
        return this.auth0Client.getTokenSilently(o);
      },
      /** Logs the user out and removes their session on the authorization server */
      logout(o) {
        return this.auth0Client.logout(o);
      }
    },
    async created() {
      // Create a new instance of the Auth0 client
      this.auth0Client = await createAuth0Client({
        domain: options.domain,
        client_id: options.clientId,
        audience: options.audience,
        redirect_uri: redirectUri
      });

      try {
        // If the user is returning to the app after authentication...
        if (
          window.location.search.includes('code=') &&
          window.location.search.includes('state=')
        ) {
          // handle the redirect and retrieve tokens
          const { appState } = await this.auth0Client.handleRedirectCallback();

          // Execute the onRedirectCallback now that tokens have been retrieved
          onRedirectCallback(appState);
        }
      } catch (e) {
        this.error = e;
      } finally {
        // Initialize our internal authentication state
        this.isAuthenticated = await this.auth0Client.isAuthenticated();
        this.user = await this.auth0Client.getUser();
        this.loading = false;
      }
    }
  });

  return instance;
};

// Create a simple Vue plugin to expose the wrapper object throughout the application
export const Auth0Plugin = {
  install(Vue, options) {
    Vue.prototype.$auth = useAuth0(options);
  }
};

3. Use the Auth0 Plugin in your app:

In your main.js (or equivalent):

import Vue from 'vue';
import { Auth0Plugin } from './auth';
import App from './App.vue';

Vue.config.productionTip = false;

Vue.use(Auth0Plugin, {
  domain: 'YOUR_AUTH0_DOMAIN',
  clientId: 'YOUR_AUTH0_CLIENT_ID',
  audience: 'YOUR_AUTH0_AUDIENCE',
  onRedirectCallback: (appState) => {
    router.push(
      appState && appState.targetUrl
        ? appState.targetUrl
        : window.location.pathname
    );
  }
});

new Vue({
  render: (h) => h(App),
}).$mount('#app');

4. Authentication in components:

Now, in your Vue components, you can use the authentication methods like so:

<template>
  <div v-if="$auth.loading">
    Loading...
  </div>
  <div v-else-if="!$auth.isAuthenticated">
    <button @click="$auth.loginWithRedirect()">Log in</button>
  </div>
  <div v-else>
    <p>Welcome, {{ $auth.user.name }}!</p>
    <button @click="$auth.logout()">Log out</button>
  </div>
</template>

This is a basic setup and should be modified according to your specific needs. Always refer to the official documentation of the library and OIDC provider for more detailed and updated information.

Resources:

  1. OIDC Client Library: One popular library used for this purpose is oidc-client-js. You can check out its GitHub repository for details on how to set it up:
  2. Vue.js OIDC Plugins: There are plugins built specifically for Vue.js that make integrating OIDC easier:
  3. Documentation: The OpenID Connect official website provides extensive documentation on how OIDC works, which will be helpful in understanding the flow and integrating it into your application:
  4. Tutorials & Blogs: Occasionally, developers write tutorials and articles about their experiences integrating OIDC with Vue.js. Websites like Medium, Dev.to, and personal developer blogs are great places to find such content.
  5. Community: When you run into challenges or have specific questions, communities such as Stack Overflow (https://stackoverflow.com/) can be invaluable. Just ensure your questions are well-framed and provide enough context for others to assist you.
  6. Vue.js Official Documentation: To ensure compatibility and understand best practices, always consult the Vue.js official documentation when integrating external libraries or plugins.

More Reading

Post navigation

Leave a Comment

Leave a Reply

Your email address will not be published. Required fields are marked *

How Fetch works in JavaScript?

Creating a Simple Express.js Server on Node.js

How to create Full Stack Application with Node.js and React ?

Mastering Loops in JavaScript: A Comprehensive Guide

Best Coding Ideas in JavaScript

How to use MySQL Database with Node.js?