vuethenticate

A Vue 3 authentication state management library using oidc-client-ts
4,051 1
Install
npm install vuethenticate
Latest Version:0.1.13
Vue:3
License:MIT
Last Updated:Jun 13, 2025
Links: GitHub  ·  npm
Maintainer: juul05

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

Related Packages

@dlukt/vue-oidc-context

OpenID Connect (OIDC) & OAuth 2.0 authentication for Vue 3 — a lightweight, full...

511 0
use-trpc

Vue composable for tRPC v10

722 12
@anchorlib/vue

Vue bindings for Anchor reactive state management

8,573 28
@phila/sso-vue

Vue 3 adapter for @phila/sso-core

1,554
oidc-js-vue

Simple OIDC authentication for Vue. Plugin, composables, and navigation guards w...

1,013 3

Version History

Version Released Vue License
0.1.13 ^3.0.0 MIT
0.1.12 ^3.0.0 MIT
0.1.11 ^3.0.0 MIT
0.1.10 ^3.0.0 MIT
0.1.9 ^3.0.0 MIT