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

Related tags

Vue.js vue-auth0
Overview

vue-auth0

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

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 the naccess the Auth0 singleton instance via useAuth0 composable.

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

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

Options

initAuth0 accepts a couple 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, 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 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 completed and cannot use onInitializationCompleted hook.

const { initializationCompleted } = useAuth0();

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

Hooks

Some common events hooks has been created, ensuring your code is executed 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 right away.

onInitializationCompleted

Trigger: Auth0 client initialization completes. Use case: run code using Auth0 if you're not sure Auth0 client is initialized already.

initializationCompleted method could be used to obtain 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 log in. User data object is provided as 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 log 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 from 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 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');
      }
    },
  },
];
You might also like...

AngularJS SPA Template for Visual Studio is a project skeleton for a simple single-page web application (SPA) built with AngularJS, Bootstrap, and ASP.NET (MVC, Web Api, SignalR).

AngularJS SPA Template for Visual Studio is a project skeleton for a simple single-page web application (SPA) built with AngularJS, Bootstrap, and ASP.NET (MVC, Web Api, SignalR).

AngularJS SPA Template for Visual Studio This project is a skeleton for a simple single-page web application (SPA) built on top of the: AngularJS 1.2.

Jun 18, 2022

A Svelte SPA Template for simple SPA Apps without using svelte kit.

Svelte SPA Template A Svelte Single Page Application Template for simple SPA Apps without using Svelte Kit or Sapper. New Project To create a new proj

Jan 24, 2022

FingerprintJS Pro Wrapper for React Single Page Applications (SPA)

FingerprintJS Pro Wrapper for React Single Page Applications (SPA)

FingerprintJS Pro React FingerprintJS Pro React is an easy-to-use React library for FingerprintJS Pro. This package works with FingerprintJS Pro, it i

Dec 15, 2022

Query for CSS brower support data, combined from caniuse and MDN, including version support started and global support percentages.

css-browser-support Query for CSS browser support data, combined from caniuse and MDN, including version support started and global support percentage

Nov 2, 2022

A small project with 3 accounts mapped to 3 resources using auth0 as an authentication service.

Auth0WithExpressJS Quickstart install dependencies for backend and start backend cd Auth0WithExpressJS\Back && npm start install dependencies for fron

Aug 21, 2021

🔐 Lambda Authorizer ready for integration with Serverless Framework and Auth0.

Getting started 1. Clone the repository (or generate a serverless project) sls create --name auth-service --template-url https://github.com/GustavoNor

Feb 10, 2022

A wee E-Commerce website powered by Stripe, Auth0, Strapi and Next.js

This is a Next.js project bootstrapped with create-next-app. Getting Started First, run the development server: npm run dev # or yarn dev Open http://

Dec 19, 2022

Real world app using Fastify-DX, Solid.js, Auth0 and GraphQL

Fastify DX and Solid.js In the Real World These are only the essentials to set up a "real world" application with Fastify DX, Solid.js, Auth0 and Grap

Nov 14, 2022

Lightweight WebSocketServer wrapper lib using ws-wrapper to wrap connected WebSockets

ws-server-wrapper Lightweight WebSocketServer wrapper lib using ws-wrapper and ws to wrap connected WebSockets. The only dependency is ws-wrapper itse

May 9, 2022

A full NodeJS sms-activate.org api wrapper up to date in Typescript

Sms-Activate.org This package fully supports all the https://sms-activate.org/ API with Typescript types. Installation Install the package using npm

Dec 26, 2022

local storage wrapper for both react-native and browser. Support size controlling, auto expiring, remote data auto syncing and getting batch data in one query.

react-native-storage This is a local storage wrapper for both react native apps (using AsyncStorage) and web apps (using localStorage). ES6 syntax, pr

Dec 16, 2022

ApostropheCMS is a full-featured, open-source CMS built with Node.js that seeks to empower organizations by combining in-context editing and headless architecture in a full-stack JS environment.

ApostropheCMS ApostropheCMS is a full-featured, open source CMS built with Node.js that seeks to empower organizations by combining in-context editing

Jan 4, 2023

ApostropheCMS is a full-featured, open-source CMS built with Node.js that seeks to empower organizations by combining in-context editing and headless architecture in a full-stack JS environment.

ApostropheCMS ApostropheCMS is a full-featured, open source CMS built with Node.js that seeks to empower organizations by combining in-context editing

Jan 4, 2023

A Full Stack Amazon Clone which created using ReactJS with full E-Commerce Functionality!!

Amazon Clone with ReactJS A small web app that tries to imitate the desktop web version of amazon site, you can add items to the basket, delete them,

Oct 3, 2022

This is a full-stack exercise tracker web application built using the MERN (MongoDB, ExpressJS, ReactJS, NodeJS) stack. You can easily track your exercises with this Full-Stack Web Application.

Getting Started with Create React App This project was bootstrapped with Create React App. Available Scripts In the project directory, you can run: np

Dec 25, 2021

noUiSlider is a lightweight JavaScript range slider library with full multi-touch support. It fits wonderfully in responsive designs and has no dependencies.

noUiSlider is a lightweight JavaScript range slider library with full multi-touch support. It fits wonderfully in responsive designs and has no dependencies.

noUiSlider noUiSlider is a lightweight JavaScript range slider. No dependencies All modern browsers and IE 9 are supported Fully responsive Multi-to

Dec 28, 2022

Full CSS support for JSX without compromises

Full CSS support for JSX without compromises

styled-jsx Need help? Full, scoped and component-friendly CSS support for JSX (rendered on the server or the client). Code and docs are for v3 which w

Jan 4, 2023

Use full ES2015+ features to develop Node.js applications, Support TypeScript.

Use full ES2015+ features to develop Node.js applications, Support TypeScript.

ThinkJS Use full ES2015+ features to develop Node.js applications, Support TypeScript. 简体中文文档 Installation npm install -g think-cli Create Application

Dec 30, 2022

A reimplementation of Winamp 2.9 in HTML5 and JavaScript with full skin support

A reimplementation of Winamp 2.9 in HTML5 and JavaScript with full skin support

A reimplementation of Winamp 2.9 in HTML5 and JavaScript with full skin support

Dec 31, 2022
Comments
  • README.md updates

    README.md updates

    These are the things I noticed right now. About removing some abbreviation like "they're", it because, when in positive form, it is usually considered better to avoid contraction of the words when writing a text. In addition, I was wondering if the package also supports JS projects out of the box. This maybe worth a mention.

    opened by SirAuron 2
  • If user declines social oauth, auth needs to logout

    If user declines social oauth, auth needs to logout

    1. Click $auth.loginWithRedirect() button.
    2. Choose a Google social signup option.
    3. Click decline
    4. User is returned back to app but next time they click login button it brings the user back to the social request page.

    I believe if the URL has ?error=access_denied params then a $auth.logout() call needs to happen to allow the user to choose a different login method on Auth0

    opened by alexcroox 1
Owner
Dreamonkey S.r.l.
We deal with websites, web design, graphics, Android app and counsellings. We try to release as open source useful code we develop for our projects.
Dreamonkey S.r.l.
Real world app using Fastify-DX, Solid.js, Auth0 and GraphQL

Fastify DX and Solid.js In the Real World These are only the essentials to set up a "real world" application with Fastify DX, Solid.js, Auth0 and Grap

Zentered 6 Nov 14, 2022
A svelte action for creating tippy.js tooltips with full typescript support

Tippy.js for svelte A svelte action for creating tippy.js tooltips. Getting started # Pnpm pnpm add svelte-tippy tippy.js # Yarn yarn add svelte-tipp

Brett Mandler 11 Jul 19, 2022
:bento: Full-Stack solution to quickly build PWA applications with Vue.js and Firebase

Welcome to bento-starter ?? ?? bento-starter is an Open-Source Full-Stack solution that helps you to build fast and maintainable web applications usin

Franck Abgrall 1.5k Dec 24, 2022
demo for full-stack ci/cd

vue + nestjs (TypeScript) Features CI/CD full-stack mutiple-env (test: http://81.70.221.165:8026 / production: http://81.70.221.165) continuing~ welco

Evan Zuo 3 Oct 24, 2022
Frolics is an offline, lightweight, full-text search library for Frontend applications

Frolics What Is Frolics Installation Document Preparing Customized Fields Hand-on Example Cache Usage What Is Frolics ? Frolics is an offline, lightwe

null 13 Dec 4, 2022
Nuxt-Module, that provides a system to set shopware cache-tags for later use in e.g. a full-page cache

nuxt-shopware-caching Nuxt-Module, that provides a system to set shopware cache-tags for later use in e.g. a full-page cache. This module is meant to

Mothership GmbH 5 Nov 8, 2022
Manage HTML metadata in Vue.js components with SSR support

✌️ ?? Check the next branch for Vue3 support Manage HTML metadata in Vue.js components with SSR support <template> ... </template> <script> expor

Nuxt 4k Jan 1, 2023
A multi-select component with nested options support for Vue.js

vue-treeselect A multi-select component with nested options support for Vue.js Features Single & multiple select with nested options support Fuzzy mat

Fangzhou Li 2.6k Jan 5, 2023
🐝 A vite plugin automatically export files & HMR support

vite-plugin-hot-export Automatically export files with HMR English|简体中文 Why ? When developing, we often need to download some images or svg from the i

Frozen FIsh 54 Nov 12, 2022
⚡️The Fullstack React Framework — built on Next.js

The Fullstack React Framework "Zero-API" Data Layer — Built on Next.js — Inspired by Ruby on Rails Read the Documentation “Zero-API” data layer lets y

⚡️Blitz 12.5k Jan 4, 2023