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 🙏

© 2025 – Pkg Stats / Ryan Hefner

vuethenticate

v0.1.13

Published

A Vue 3 authentication state management library using oidc-client-ts

Downloads

316

Readme

Vuethenticate

A Vue 3 authentication state management library using oidc-client-ts.

Features

  • 🔐 OIDC/OAuth2 authentication with automatic token management
  • ⚡ Vue 3 Composition API with reactive state
  • 🔄 Automatic token renewal
  • 📦 TypeScript support
  • 🎯 Minimal configuration required
  • 🎨 Customizable callback component

Installation

npm install vuethenticate

Quick Start

Important Setup Order: Make sure to initialize useAuth() in your main App component or a parent component before any callback routes are accessible. The callback components depend on this initialization.

1. Configure Authentication

<!-- App.vue - Main Application Component -->
<script setup>
import { useAuth } from 'vuethenticate'
import { RouterView } from 'vue-router'

// Initialize authentication in your main app component
const { user, isAuthenticated, signIn, signOut } = useAuth({
  authority: 'https://your-oidc-provider.com',
  clientId: 'your-client-id'
})
</script>

<template>
  <div id="app">
    <nav>
      <div v-if="isAuthenticated">
        <p>Welcome, {{ user.profile.name }}!</p>
        <button @click="signOut">Sign Out</button>
      </div>
      <div v-else>
        <button @click="signIn">Sign In</button>
      </div>
    </nav>
    
    <!-- Router outlet - callback routes will work properly now -->
    <RouterView />
  </div>
</template>

2. Setup Callback Route

<!-- CallbackPage.vue -->
<script setup>
import { AuthCallback } from 'vuethenticate'

function onSuccess(user, state) {
  console.log('Authentication successful:', user)
  console.log('State:', state)
  // Redirect to app or show success message
  window.location.href = '/dashboard'
}

function onError(error) {
  console.error('Authentication failed:', error)
  // Handle error - redirect to login or show error
  window.location.href = '/login'
}
</script>

<template>
  <AuthCallback 
    :onSuccess="onSuccess"
    :onError="onError"
  >
    <div>Signing you in...</div>
    
    <template #error="{ error }">
      <div>
        <h2>Authentication Failed</h2>
        <p>{{ error.message }}</p>
      </div>
    </template>
  </AuthCallback>
</template>

3. Add Route Configuration

// router.js
import { createRouter, createWebHistory } from 'vue-router'
import CallbackPage from './CallbackPage.vue'
import LogoutCallbackPage from './LogoutCallbackPage.vue'
import SilentCallbackPage from './SilentCallbackPage.vue'

const routes = [
  {
    path: '/auth/callback',
    component: CallbackPage
  },
  {
    path: '/auth/logout-callback',
    component: LogoutCallbackPage
  },
  {
    path: '/auth/silent-callback',
    component: SilentCallbackPage
  },
  // ... other routes
]

export default createRouter({
  history: createWebHistory(),
  routes
})

4. Setup Silent Callback (for Token Renewal)

<!-- SilentCallbackPage.vue -->
<script setup>
import { SilentCallback } from 'vuethenticate'

function onError(error) {
  console.error('Silent renewal failed:', error)
}
</script>

<template>
  <SilentCallback :onError="onError" />
</template>

URL State Support

You can pass state through the authentication flow with full TypeScript support:

// Define your state type
interface MyAppState {
  returnUrl: string;
  theme: 'light' | 'dark';
  userId?: string;
}

// Use with generic type parameter
const auth = useAuth<MyAppState>(config);

// Pass state during sign in
await auth.signIn({
  returnUrl: '/dashboard',
  theme: 'dark'
});

// Pass state during sign out  
await auth.signOut({
  returnUrl: '/goodbye',
  theme: 'light'
});

Receiving State in Callback

<script setup lang="ts">
import { AuthCallback } from 'vuethenticate';

interface MyAppState {
  returnUrl: string;
  theme: 'light' | 'dark';
}

const handleSuccess = (user: User, state?: MyAppState) => {
  if (state?.returnUrl) {
    router.push(state.returnUrl);
  }
  if (state?.theme) {
    setTheme(state.theme);
  }
};
</script>

<template>
  <AuthCallback<MyAppState>
    @success="handleSuccess"
  />
</template>

Important: Make sure to call useAuth() in your main App component or a parent component before rendering any callback components. The callback components rely on the authentication being initialized first.

API Reference

useAuth(config)

The main composable for authentication state management.

Configuration

| Property | Type | Required | Default | Description | |----------|------|----------|---------|-------------| | authority | string | ✓ | - | OIDC provider URL | | clientId | string | ✓ | - | Application client ID | | redirectUri | string | | ${origin}/auth/callback | Callback URL | | scope | string | | 'openid profile' | OIDC scopes | | responseType | string | | 'code' | OAuth response type | | storage | 'localStorage' \| 'sessionStorage' \| 'memory' | | 'localStorage' | Storage type | | automaticSilentRenew | boolean | | true | Enable automatic token refresh | | silentRedirectUri | string | | ${origin}/auth/silent-callback | Silent refresh callback URL | | postLogoutRedirectUri | string | | ${origin} | Post-logout redirect URL | | logLevel | LogLevel | | LogLevel.NONE | Logging level for debug information | | logger | Logger | | silentLogger | Custom logger implementation |

Event Callbacks

| Property | Type | Description | |----------|------|-------------| | onError | (error: Error) => void | Called when an error occurs | | onUserLoaded | (user: User) => void | Called when user is loaded | | onUserUnloaded | () => void | Called when user is unloaded | | onAccessTokenExpired | () => void | Called when access token expires | | onAccessTokenExpiring | () => void | Called before access token expires | | onSilentRenewError | (error: Error) => void | Called when silent token renewal fails (auth state is automatically reset) |

Returns

| Property | Type | Description | |----------|------|-------------| | user | Ref<User \| null> | Current user object | | isAuthenticated | Ref<boolean> | Authentication status | | isLoading | Ref<boolean> | Loading state | | error | Ref<Error \| null> | Current error | | accessToken | Ref<string \| null> | Current access token | | isExpired | Ref<boolean> | Token expiration status | | signIn | (state?: TState) => Promise<void> | Initiate sign in with optional state | | signOut | (state?: TState) => Promise<void> | Sign out user with optional state | | silentRenew | () => Promise<void> | Manually renew token | | clearError | () => void | Clear current error | | resetAuthState | () => Promise<void> | Manually reset authentication state by removing user and clearing reactive state | | cleanup | () => void | Manual cleanup of UserManager resources (rarely needed) |

<AuthCallback>

Component for handling OAuth callback. Note: This component requires useAuth() to be called in a parent component first.

Props

| Property | Type | Required | Description | |----------|------|----------|-------------| | onSuccess | (user: User, state?: TState) => void | | Success callback with typed state | | onError | (error: Error) => void | | Error callback |

Slots

| Slot | Props | Description | |------|-------|-------------| | default | - | Loading content | | error | { error: Error } | Error content |

Events

| Event | Payload | Description | |-------|---------|-------------| | success | User, state?: TState | Emitted on successful authentication with typed state | | error | Error | Emitted on authentication error |

<LogoutCallback>

Component for handling OAuth logout callback. Note: This component requires useAuth() to be called in a parent component first.

Props

| Property | Type | Required | Description | |----------|------|----------|-------------| | onSuccess | (state?: TState) => void | | Success callback with typed state | | onError | (error: Error) => void | | Error callback |

Slots

| Slot | Props | Description | |------|-------|-------------| | default | - | Loading content | | error | { error: Error } | Error content | | success | - | Success content |

Events

| Event | Payload | Description | |-------|---------|-------------| | success | state?: TState | Emitted on successful logout with typed state | | error | Error | Emitted on logout error |

Usage

<!-- LogoutCallbackPage.vue -->
<script setup>
import { LogoutCallback } from 'vuethenticate'

function onSuccess(state) {
  console.log('Logout successful:', state)
  // Redirect to home or show success message
  window.location.href = '/'
}

function onError(error) {
  console.error('Logout failed:', error)
  // Handle error - redirect or show error
  window.location.href = '/error'
}
</script>

<template>
  <LogoutCallback 
    :onSuccess="onSuccess"
    :onError="onError"
  >
    <div>Processing logout...</div>
    
    <template #error="{ error }">
      <div>
        <h2>Logout Failed</h2>
        <p>{{ error.message }}</p>
      </div>
    </template>
    
    <template #success>
      <div>
        <h2>Logout Successful</h2>
        <p>You have been logged out successfully.</p>
      </div>
    </template>
  </LogoutCallback>
</template>

<SilentCallback>

Component for handling silent token renewal callbacks. This component should be mounted on a separate route (typically /auth/silent-callback) and is used internally by the library for automatic token refresh. Note: This component requires useAuth() to be called in a parent component first.

Props

| Property | Type | Required | Description | |----------|------|----------|-------------| | onError | (error: Error) => void | | Error callback for silent renewal failures |

Usage

<template>
  <SilentCallback :onError="handleSilentError" />
</template>

<script setup>
import { SilentCallback } from 'vuethenticate'

function handleSilentError(error) {
  console.error('Silent renewal failed:', error)
}
</script>

Note: This component is primarily used in an iframe or popup for silent token renewal. It should be placed on a minimal page with no other content.

Logging and Debugging

Vuethenticate provides comprehensive logging capabilities to help debug authentication flows and monitor authentication events. The logging system supports both internal library logging and configurable oidc-client-ts debug output.

Log Levels

import { LogLevel } from 'vuethenticate';

enum LogLevel {
    NONE = 0,    // No logging
    ERROR = 1,   // Only errors
    WARN = 2,    // Warnings and errors
    INFO = 3,    // Info, warnings, and errors
    DEBUG = 4,   // All messages including debug info
}

Basic Logging Setup

import { useAuth, LogLevel, consoleLogger } from 'vuethenticate';

// Enable debug logging with console output
const auth = useAuth({
    authority: 'https://your-oidc-provider.com',
    clientId: 'your-client-id',
    logLevel: LogLevel.DEBUG,
    logger: consoleLogger
});

Custom Logger Implementation

import { useAuth, LogLevel, type Logger } from 'vuethenticate';

const customLogger: Logger = {
    error: (message: string, ...args: unknown[]) => {
        // Send to your error tracking service
        console.error('[AUTH ERROR]', message, ...args);
        // Sentry.captureException(new Error(message));
    },
    warn: (message: string, ...args: unknown[]) => {
        console.warn('[AUTH WARN]', message, ...args);
    },
    info: (message: string, ...args: unknown[]) => {
        console.info('[AUTH INFO]', message, ...args);
    },
    debug: (message: string, ...args: unknown[]) => {
        if (process.env.NODE_ENV === 'development') {
            console.debug('[AUTH DEBUG]', message, ...args);
        }
    },
};

const auth = useAuth({
    authority: 'https://your-oidc-provider.com',
    clientId: 'your-client-id',
    logLevel: LogLevel.INFO,
    logger: customLogger
});

Environment-Based Logging

import { useAuth, LogLevel, consoleLogger } from 'vuethenticate';

const getLogConfig = () => {
    switch (process.env.NODE_ENV) {
        case 'development':
            return { logLevel: LogLevel.DEBUG, logger: consoleLogger };
        case 'test':
            return { logLevel: LogLevel.NONE };
        case 'production':
            return { logLevel: LogLevel.ERROR, logger: productionLogger };
        default:
            return { logLevel: LogLevel.WARN, logger: consoleLogger };
    }
};

const auth = useAuth({
    authority: 'https://your-oidc-provider.com',
    clientId: 'your-client-id',
    ...getLogConfig()
});

Available Loggers

consoleLogger

Standard console output logger suitable for development.

silentLogger

No-op logger that suppresses all output (default when no logger is specified).

createLevelLogger(baseLogger, level)

Creates a filtered logger that only outputs messages at or above the specified level.

import { createLevelLogger, consoleLogger, LogLevel } from 'vuethenticate';

const warnOnlyLogger = createLevelLogger(consoleLogger, LogLevel.WARN);

What Gets Logged

When logging is enabled, you'll see output for:

  • Authentication initialization - Setup and configuration validation
  • Token operations - Token acquisition, renewal, and expiration
  • User state changes - Login, logout, and user profile updates
  • Silent renewal - Background token refresh attempts
  • OIDC protocol flows - Detailed protocol-level debugging (when DEBUG level)
  • Error conditions - All authentication-related errors with context

OIDC Client Debug Logs

The underlying oidc-client-ts library has extensive debug logging. When you configure logging in Vuethenticate, it automatically configures the OIDC client logging as well, so you'll see detailed protocol-level information including:

  • HTTP requests and responses
  • Token validation steps
  • Silent renewal iframe operations
  • OIDC discovery document processing

Production Considerations

For production environments, consider:

  • Setting logLevel to LogLevel.ERROR or LogLevel.NONE
  • Using a custom logger that sends errors to your monitoring service
  • Avoiding debug-level logging to prevent performance impact
  • Implementing log sampling for high-traffic applications
// Production-safe logging configuration
const auth = useAuth({
    authority: 'https://your-oidc-provider.com',
    clientId: 'your-client-id',
    logLevel: LogLevel.ERROR,
    logger: {
        error: (message, ...args) => {
            // Send to monitoring service
            monitoringService.error(message, args);
        },
        warn: () => {}, // Suppress in production
        info: () => {}, // Suppress in production  
        debug: () => {}, // Suppress in production
    }
});

Logging

Vuethenticate provides comprehensive logging support for debugging authentication flows and OIDC protocol interactions. Logging is silent by default - you must explicitly configure it to see output.

Configuration

Add logging configuration to your auth config:

import { useAuth, LogLevel, consoleLogger } from 'vuethenticate'

const auth = useAuth({
  authority: 'https://your-oidc-provider.com',
  clientId: 'your-client-id',
  
  // Enable debug logging
  logLevel: LogLevel.DEBUG,
  // logger: consoleLogger, // Optional: defaults to console when logLevel is set
})

Log Levels

| Level | Value | Description | |-------|-------|-------------| | LogLevel.NONE | 0 | No logging (default) | | LogLevel.ERROR | 1 | Error messages only | | LogLevel.WARN | 2 | Warnings and errors | | LogLevel.INFO | 3 | Info, warnings, and errors | | LogLevel.DEBUG | 4 | All messages including debug info |

Built-in Loggers

| Logger | Description | |--------|-------------| | consoleLogger | Logs to browser console (used automatically when logLevel is set) | | silentLogger | No output - useful for explicitly disabling logs |

Behavior

  • Silent by default: No logging occurs unless explicitly configured
  • Smart defaults: When you set a logLevel, consoleLogger is used automatically
  • Custom loggers: Provide your own logger for custom logging behavior
  • OIDC integration: Both internal auth logs and underlying OIDC client logs are controlled by the same configuration

Custom Logger

Implement the Logger interface for custom logging:

import type { Logger } from 'vuethenticate'

const customLogger: Logger = {
  error: (message, ...args) => {
    // Send to error reporting service
    errorService.log(message, args)
  },
  warn: (message, ...args) => console.warn(message, ...args),
  info: (message, ...args) => console.info(message, ...args),
  debug: (message, ...args) => {
    if (process.env.NODE_ENV === 'development') {
      console.debug(message, ...args)
    }
  },
}

const auth = useAuth({
  authority: 'https://your-oidc-provider.com',
  clientId: 'your-client-id',
  logLevel: LogLevel.INFO,
  logger: customLogger,
})

What Gets Logged

With logging enabled, you'll see detailed information about:

  • Authentication flows: Sign-in, sign-out, and callback processing
  • Token management: Token refresh, expiration, and renewal
  • OIDC protocol: Requests, responses, and protocol-level details
  • Error handling: Detailed error information with stack traces
  • State management: User loading/unloading events

Development vs Production

const auth = useAuth({
  authority: 'https://your-oidc-provider.com',
  clientId: 'your-client-id',
  
  // Enable detailed logging only in development
  logLevel: process.env.NODE_ENV === 'development' 
    ? LogLevel.DEBUG 
    : LogLevel.ERROR,
})

Advanced Usage

Manual Authentication State Reset

The resetAuthState() method provides a way to manually clear authentication state and remove the user from storage. This is useful for custom logout flows or error recovery scenarios.

const auth = useAuth(config);

// Manually reset authentication state
await auth.resetAuthState();

// This will:
// - Remove user from storage
// - Clear reactive user state
// - Log the operation
// - Handle any errors that occur during removal

Common use cases:

  • Custom logout flows that don't use the standard OAuth logout endpoint
  • Error recovery when authentication state becomes corrupted
  • Implementing "sign out from all devices" functionality
  • Testing scenarios where you need to reset authentication state

Error Handling and State Recovery

All callback components (AuthCallback, LogoutCallback, SilentCallback) now automatically handle errors by resetting authentication state. When an error occurs during callback processing:

  1. The error is logged with appropriate details
  2. Authentication state is automatically reset via resetAuthState()
  3. The error is re-thrown for your application to handle

This ensures that failed authentication flows don't leave the application in an inconsistent state.

// Callback components automatically handle errors and reset state
// No additional error handling required for state consistency

Manual Cleanup

The useAuth composable includes a cleanup() function for manual resource cleanup. This is rarely needed as the library manages resources automatically.

const auth = useAuth(config);

// Only use in special scenarios like testing or custom cleanup requirements
auth.cleanup();

When you might need cleanup:

  • Unit testing scenarios where you need to reset state between tests
  • Dynamic configuration changes (though creating a new instance is usually better)
  • Custom cleanup logic in very specific edge cases

Note: The cleanup function removes event listeners and clears the UserManager instance from the internal registry. Normal application usage should never require calling this function.

License

MIT