npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@dreamonkey/vue-auth0

v1.0.0

Published

@auth0/auth0-spa-js wrapper in the 'Vue way', with full TS support

Downloads

190

Readme

vue-auth0

This is a wrapper around @auth0/auth0-spa-js meant to ease its usage into Vue3 projects. This is heavily inspired by the snippet into Auth0 official documentation, but with a couple more helpers.

This wrapper supports both JS and TS codebases.

Install

yarn add @dreamonkey/vue-auth0

Initialize the singleton instance

import { Auth0Instance, initAuth0 } from '@dreamonkey/vue-auth0';
// NEVER HARDCODE AND/OR COMMIT YOUR SECRETS
import { domain, clientId } from './env.json';

declare module '@vue/runtime-core' {
  interface ComponentCustomProperties {
    $auth: Auth0Instance;
  }
}

// Vue CLI/Vite project
import { createApp } from 'vue';

const app = createApp({});

app.config.globalProperties.$auth = initAuth0({
  client_id: clientId,
  domain,
});

// Quasar CLI project (using boot files)
export default boot(({ app }) => {
  app.config.globalProperties.$auth = initAuth0({
    client_id: clientId,
    domain,
  });
});

Check out @auth0/auth0-spa-js documentation to learn about initialization options, as initAuth0 accepts all options from original createAuth0Client method.

You can then access the Auth0 singleton instance via useAuth0 composable

import { useAuth0 } from '@dreamonkey/vue-auth0';

const { user /*, ... other stuff */ } = useAuth0();

or, in templates or Option API, via the $auth global property

<button @click="$auth.loginWithRedirect()">Login</button>

Options

initAuth0 accepts a couple of custom options in addition to those of createAuth0Client method.

redirectUri (default: window.location.origin)

Overwrites native redirect_uri option setting a sensible default for it. If your redirect login flow starts from a page with URL http://my-domain.com/landing, the user will be redirected to http://my-domain.com when the flow completes.

Remember you need to add whichever URL is provided with redirectUri to "Allowed Callback URLs" list into your Auth0 configuration.

onRedirectCallback

When redirect login flow completes, this callback is called with any previously stored state as param. If not specified, it replaces the current browser history entry with current window.location.pathname. This can be used to redirect the user to the originally requested page after login took place (see Recipes section).

Reactive refs

These refs has been added for your ease, to consume Auth0 SDK in the "Vue way"

user (default: undefined)

The original getUser() async method served as a reactive reference. It updates when either a login or logout action is performed. The content after login depends on your Auth0 configuration.

const { user } = useAuth0();
// Before login
console.log(user.value); // undefined
// After login
console.log(user.value); // { ... }

Its type is User by default, you can augment Auth0User type to specify custom properties or to remove optionality from existing keys.

import '@dreamonkey/vue-auth0';

declare module '@dreamonkey/vue-auth0' {
  interface Auth0User {
    twitter_handle: string; // <--- Specify a custom property which doesn't exist into User by default
    name: string; // <--- Override User property, it won't be shown as optional anymore
  }
}

isAuthenticated (default: false)

The original isAuthenticated() async method served as a reactive reference. true if the user is authenticated, false otherwise. Helpful to change the behaviour of your app depending on the user authentication status, eg. adding an header to all outgoing requests only when the user is authenticated

const { isAuthenticated } = useAuth0();
// Before login
console.log(isAuthenticated.value); // false
// After login
console.log(isAuthenticated.value); // true

loading (default: true)

true if Auth0 client initialization is still taking place, false when initialization completes.

popupOpen (default: false)

true if the login popup related to loginWithPopup() method is open, false otherwise.

error (default: undefined)

Contains the error generated by the underlying library in case something goes wrong.

auth0Client (default: undefined)

Reference to the underlying Auth0 client created with original createAuth0Client() method.

Methods

getTokenSilently

Original getTokenSilently method with detailedResponse forced to false. This is how the method behaved before version 1.19.0.

getTokenSilentlyVerbose

Original getTokenSilently method with detailedResponse forced to true. Splitting the original method was required to support proper types, as wrapping a function and trying to infer its return type won't work if the original function has an overloaded signature.

initializationCompleted

Returns a Promise resolving when initialization completes. Use this when you need to be sure initialization is completed and you cannot use onInitializationCompleted hook.

const { initializationCompleted } = useAuth0();

async function doStuff() {
  // business ah-ah
  await initializationCompleted();
  // profit!
}

Hooks

Some common events hooks have been created, ensuring your code will be executed only after a given trigger condition is met. Since they're based on internal state refs rather than an event system, if the trigger condition is valid when the hook is registered (eg. login already happened) the callback will be executed immediately.

onInitializationCompleted

Trigger: Auth0 client initialization completes. Use case: run code using Auth0 only after the client is initialized.

initializationCompleted method could be used to achieve the same result, but with a different syntax.

const { onInitializationCompleted } = useAuth0();

onInitializationCompleted(() => {
  // unless initialization errors occurred, auth0Client will always be defined here
});

onLogin

Trigger: login process completes successfully. Use case: run code once the user logs in. User data object is provided as a parameter for convenience.

Examples:

  • initialize analytics only for authenticated users;
  • establish a websocket connection once the user is authenticated;
  • add an inactivity timeout.
const { onLogin } = useAuth0();

onLogin((user) => {
  console.log(user); // { .. user data .. }
});

onLogout

Trigger: logout process completes. Use case: run code once the user logs out.

Examples:

  • cleanup user-related data;
  • interrupt a websocket connection reserved to authenticated users.
const { onLogout } = useAuth0();

onLogout(() => {
  localStorage.removeItem('user-data');
});

Vue Router Guards

If you're using Vue Router, you'll often need to guard some routes depending on the user authentication status. This package provides you some helpers to deal with common scenarios.

authGuard

Use this helper to create guards relying on the user authentication status. The first param your callback receives is a boolean representing the authentication status, while the second and third params are the deprecated to and from Vue Router guards params. The returned guard is async as it awaits for the Auth0 client to be initialized before proceeding.

export const redirectIfAuthenticatedGuard = authGuard((isAuthenticated) => {
  if (isAuthenticated) {
    return { name: 'home' };
  }
});

redirectToLoginGuard

Triggers loginWithRedirect if the user isn't authenticated, storing into appState.targetUrl the URL the user tried to access. You can then access it into onRedirectCallback to redirect the user to the page he initially requested.

Recipes

Here are some common use cases you may need in your projects. We'll gladly accept PRs adding new recipes if the use case is common enough.

Add access token as Authorization header using Axios

import { useAuth0 } from '@dreamonkey/vue-auth0';
import axios, { AxiosRequestConfig } from 'axios';

async function addAuthToken(config: AxiosRequestConfig) {
  const { getTokenSilently } = useAuth0();
  const token = await getTokenSilently();
  addHeader(config, 'Authorization', `Bearer ${token}`);
  return config;
}

axios.interceptors.request.use(addAuthToken);

Redirect to requested page after login

import { initAuth0 } from '@dreamonkey/vue-auth0';
import { useRouter } from 'vue-router';
import { domain, clientId } from './env.json';

const router = useRouter();

initAuth0<{ targetUrl?: string }>({
  client_id: clientId,
  domain,
  onRedirectCallback: (appState) =>
    router.push(appState?.targetUrl ?? window.location.pathname),
});
import { RouteRecordRaw } from 'vue-router';
import { redirectToLoginGuard } from '@dreamonkey/vue-auth0';

const routes: RouteRecordRaw[] = [
  {
    path: '/',
    component: () => import('layouts/authenticated.vue'),
    beforeEnter: redirectToLoginGuard,
    children: [
      {
        path: 'home',
        name: 'home',
        component: () => import('pages/home.vue'),
      },
    ],
  },
];

Guard guest and authenticated pages

import { RouteRecordRaw } from 'vue-router';
import { authGuard } from '@dreamonkey/vue-auth0';

export const redirectIfAuthenticatedGuard = authGuard((isAuthenticated) => {
  if (isAuthenticated) {
    return { name: 'home' };
  }
});

export const redirectIfGuestGuard = authGuard((isAuthenticated) => {
  if (!isAuthenticated) {
    return { name: 'landing' };
  }
});

const routes: RouteRecordRaw[] = [
  {
    path: '/',
    redirect: () => ({ name: 'landing' }),
  },
  {
    path: '/',
    name: 'guest',
    component: () => import('layouts/guest.vue'),
    beforeEnter: redirectIfAuthenticatedGuard,
    children: [
      {
        path: 'landing',
        name: 'landing',
        component: () => import('pages/landing.vue'),
      },
    ],
  },
  {
    path: '/',
    component: () => import('layouts/authenticated.vue'),
    beforeEnter: redirectIfGuestGuard,
    children: [
      {
        path: 'home',
        name: 'home',
        component: () => import('pages/home.vue'),
      },
    ],
  },
];

Render a different page depending on authentication status

import { RouteRecordRaw } from 'vue-router';
import { useAuth0 } from '@dreamonkey/vue-auth0';

const routes: RouteRecordRaw[] = [
  {
    path: '/home',
    component: async () => {
      const { user, initializationCompleted } = useAuth0();
      await initializationCompleted();

      if (!user.value) {
        return import('pages/landing.vue');
      }

      switch (user.value.role) {
        case 'admin':
          return import('pages/home/admin.vue');
        case 'manager':
          return import('pages/home/manager.vue');
        default:
          return import('pages/home/user.vue');
      }
    },
  },
];