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 to use MySQL Database with Node.js?

Sorting arrays in Javascript using array.sort()

How to find keys of an object using javascript

How Fetch works in JavaScript?

How event loops works in Javascript?

Best Coding Ideas in JavaScript