@crystaltech/shared-auth

v0.5.3

Published

A shared authentication module for Crystal HIS applications using Keycloak, providing comprehensive authentication, authorization, and organization-specific access control.

Readme

@crystaltech/shared-auth

A shared authentication module for Crystal HIS applications using Keycloak, providing comprehensive authentication, authorization, and organization-specific access control.

Installation

npm install @crystaltech/shared-auth

Quick Start

import { AuthProvider, LoginComponent } from '@crystaltech/shared-auth';

const App = () => {
  return (
    <AuthProvider backendUrl="your-backend-url">
      <LoginComponent 
        onLoginSuccess={() => console.log('Login successful')}
        onLoginError={(error) => console.error('Login failed:', error)}
      />
    </AuthProvider>
  );
};

Core Components

AuthProvider

The root component that provides authentication context to your application. It handles token management, automatic token refresh, user session management, and displays session expiration notifications.

import { AuthProvider } from '@crystaltech/shared-auth';

const App = () => {
  return (
    <AuthProvider 
      backendUrl="your-backend-url"
      autoRelogin={true}
      cleanupOptions={{
        scope: 'conservative', // 'conservative' | 'full'
        clearStorage: true,
        clearCaches: false,
        clearIndexedDB: true,
        clearServiceWorkers: false,
        storageKeys: ['custom_key'] // Optional custom keys to clear
      }}
      // The AuthProvider will automatically handle:
      // - Token management
      // - Automatic token refresh
      // - User session management
      // - SSO integration
      // - Session expiration UI notifications
      // - Enhanced error handling with detailed context
    >
      {/* Your app components */}
    </AuthProvider>
  );
};

Session Expiration UI Banner

The AuthProvider automatically displays a Material-UI banner when the user's session expires, providing:

  • Auto-hide: Banner disappears after 8 seconds
  • Re-open logic: Reappears after 30 seconds if session is still expired and not dismissed
  • Action buttons: "Sign in" and "Dismiss" options
  • Error details: Sanitized error information including URL and status
  • Non-intrusive: Positioned at top-center with warning styling

The banner integrates seamlessly with your app's Material-UI theme and provides a smooth user experience during authentication issues.

Cleanup Options

Configure how the AuthProvider cleans up application state during logout:

interface CleanupOptions {
  scope?: 'conservative' | 'full';     // Cleanup scope
  clearStorage?: boolean;              // Clear localStorage/sessionStorage
  clearCaches?: boolean;               // Clear browser caches
  clearIndexedDB?: boolean;            // Clear IndexedDB
  clearServiceWorkers?: boolean;       // Unregister service workers
  storageKeys?: string[];              // Custom storage keys to clear
}
  • Conservative (default): Clears only authentication-related data
  • Full: Performs comprehensive cleanup including caches and service workers

LoginComponent

A Material-UI based login component with customizable UI and behavior. Supports custom styling and event handlers.

import { LoginComponent } from '@crystaltech/shared-auth';

const Login = () => {
  return (
    <LoginComponent
      // Event Handlers
      onLoginSuccess={(userInfo) => console.log('Login successful:', userInfo)}
      onLoginError={(error) => console.error('Login failed:', error)}
      
      // UI Customization
      title="Welcome Back"
      loginButtonText="Sign In"
      logoutButtonText="Sign Out"
      welcomeText="Hello"
      
      // Styling
      containerSx={{ mt: 4 }}
      paperSx={{ p: 4 }}
      loginButtonProps={{ 
        size: 'large',
        variant: 'contained',
        color: 'primary'
      }}
      logoutButtonProps={{ 
        size: 'large',
        variant: 'outlined',
        color: 'error'
      }}
    />
  );
};

AuthButton

A simple, flexible authentication button component for login/logout actions. Perfect for navigation bars and headers.

import { AuthButton } from '@crystaltech/shared-auth';

const Header = () => {
  return (
    <AuthButton
      onLoginClick={() => {
        console.log('Login clicked');
        // Additional login logic
      }}
      onLogoutClick={() => {
        console.log('Logout clicked');
        // Cleanup or redirect logic
      }}
      className="auth-button"
    />
  );
};

ProtectedRoute

A component that protects routes based on authentication status and optional role requirements.

import { ProtectedRoute } from '@crystaltech/shared-auth';

const App = () => {
  return (
    <Router>
      <Routes>
        {/* Basic Protection */}
        <Route
          path="/dashboard"
          element={
            <ProtectedRoute>
              <Dashboard />
            </ProtectedRoute>
          }
        />

        {/* Role-Based Protection */}
        <Route
          path="/admin"
          element={
            <ProtectedRoute requiredRoles={['admin']}>
              <AdminDashboard />
            </ProtectedRoute>
          }
        />

        {/* Custom Redirect */}
        <Route
          path="/reports"
          element={
            <ProtectedRoute
              redirectPath="/custom-login"
              fallback={<CustomLoadingComponent />}
            >
              <Reports />
            </ProtectedRoute>
          }
        />
      </Routes>
    </Router>
  );
};

Authentication Hook

useAuth

A powerful custom hook that provides access to authentication state and methods.

import { useAuth } from '@crystaltech/shared-auth';

const UserProfile = () => {
  const { 
    userInfo,           // Current user information
    token,              // Current access token
    authenticated,      // Authentication status
    login,              // Initiate login
    logout,             // Logout user
    validateToken,      // Validate current token
    refreshTokenWithBackend,  // Force token refresh
    getUserProfile,     // Fetch user profile
    getToken           // Get current token
  } = useAuth();

  // Authentication Status Check
  if (!authenticated) {
    return <button onClick={login}>Login</button>;
  }

  // Role-Based Rendering
  const isAdmin = userInfo?.realm_access?.roles?.includes('admin');

  return (
    <div>
      <h1>Welcome, {userInfo?.name}</h1>
      {isAdmin && <AdminPanel />}
      <button onClick={logout}>Logout</button>
    </div>
  );
};

API Client Integration

The apiClient utility provides a pre-configured Axios instance for making authenticated API requests with automatic token management and enhanced error handling.

import { apiClient } from '@crystaltech/shared-auth';

// Configure API client
const api = apiClient({ 
  baseURL: 'your-backend-url',
  timeout: 5000,
  headers: {
    'Custom-Header': 'value'
  },
  onUnauthorized: (error) => {
    // Optional callback for unauthorized errors
    console.log('Unauthorized access detected:', error);
  }
});

// Making authenticated requests
const fetchData = async () => {
  try {
    // GET request
    const { data: users } = await api.get('/api/users');

    // POST request
    const { data: newUser } = await api.post('/api/users', {
      name: 'John Doe',
      email: '[email protected]'
    });

    // PUT request
    await api.put(`/api/users/${userId}`, updatedData);

    // DELETE request
    await api.delete(`/api/users/${userId}`);

    return data;
  } catch (error) {
    console.error('API request failed:', error);
    throw error;
  }
};

Enhanced Error Handling

The API client automatically handles authentication errors with:

  • Automatic Token Refresh: Seamlessly refreshes expired tokens
  • Request Retry: Retries failed requests with new tokens
  • Global Event Dispatch: Triggers shared-auth:unauthorized events
  • Enhanced Error Context: Includes URL, status, and error details
  • Fallback Handling: Graceful degradation when refresh fails

Unauthorized Event Handling

Listen for authentication events in your application:

// Listen for unauthorized events
window.addEventListener('shared-auth:unauthorized', (event) => {
  const { error, url, status } = event.detail;
  
  console.log('Unauthorized access:', {
    url,           // The URL that failed
    status,        // HTTP status code
    error          // Error details
  });
  
  // Handle the unauthorized access
  // - Show notification
  // - Redirect to login
  // - Log analytics event
});

Type Definitions

UserInfo

interface UserInfo {
  sub?: string;              // Subject identifier
  email?: string;            // User's email
  name?: string;             // Full name
  preferred_username?: string; // Preferred username
  given_name?: string;       // First name
  family_name?: string;      // Last name
  realm_access?: {
    roles?: string[];        // Realm-level roles
  };
  resource_access?: {
    account?: {
      roles?: string[];      // Resource-specific roles
    };
  };
}

AuthResponse

interface AuthResponse {
  accessToken: string;    // JWT access token
  refreshToken: string;   // Refresh token
  expiresIn: number;      // Token expiration time in seconds
  tokenType: string;      // Token type (e.g., "Bearer")
  scope?: string;         // Token scope
  idToken?: string;       // OpenID Connect ID token
  sessionState?: string;  // Session state
}

ApiClientConfig

interface ApiClientConfig {
  baseURL: string;        // Base URL for API requests
  timeout?: number;       // Request timeout in milliseconds
  headers?: Record<string, string>; // Custom headers
}

Features

  • ๐Ÿ” Secure Authentication with Keycloak

    • OAuth 2.0 and OpenID Connect compliant
    • Automatic token refresh
    • Session management
    • Enhanced error handling with detailed context
  • ๐ŸŽจ Material-UI Components

    • Customizable login interface
    • Session expiration UI banner with auto-hide/re-open
    • Responsive design
    • Theme support
  • ๐Ÿ“ TypeScript Support

    • Full type definitions
    • Type-safe hooks and components
    • IntelliSense support
  • ๐Ÿ”„ Advanced Token Management

    • Automatic token refresh
    • Token validation
    • Secure storage
    • Request retry on token refresh
  • ๐ŸŒ SSO Integration

    • Single Sign-On support
    • Silent token refresh
    • Cross-domain authentication
  • ๐Ÿ‘ฅ Multi-tenancy Support

    • Organization-specific authentication
    • Role-based access control
    • Custom claims support
  • ๐Ÿ”‘ Role-Based Access Control (RBAC)

    • Fine-grained authorization
    • Role-based route protection
    • Permission-based rendering
  • ๐Ÿ›ก๏ธ Protected Routes

    • Authentication-based protection
    • Role-based protection
    • Custom redirect handling
  • ๐ŸŽฏ Authentication Hooks

    • Easy state management
    • Authentication utilities
    • Type-safe interfaces
    • Session expiration state
  • ๐Ÿ”Œ Enhanced API Integration

    • Pre-configured API client
    • Automatic token injection
    • Advanced error handling
    • Global unauthorized event dispatch
    • Request retry mechanism
  • ๐Ÿงน Configurable Cleanup

    • Conservative and full cleanup modes
    • Custom storage key management
    • IndexedDB and cache clearing
    • Service worker management
  • ๐Ÿ”” User Experience

    • Non-intrusive session expiration notifications
    • Actionable error messages with dismiss/sign-in options
    • Seamless token refresh without user interruption

Changelog

Version 0.4.3-alpha-0

๐Ÿ†• New Features

  • Session Expiration UI Banner: Automatic Material-UI banner for session expiration with dismiss and sign-in actions
  • Enhanced Error Handling: Improved handleUnauthorized with sanitized error messages including URL and status details
  • Configurable Cleanup Options: Added CleanupOptions for customizable logout cleanup behavior

๐Ÿ”ง Improvements

  • Unauthorized Event Enhancement: Added url and status to shared-auth:unauthorized event payload
  • Login Callback Optimization: Improved effect dependencies to prevent unnecessary re-runs
  • Error Context: Better error reporting with request context and sanitized messages

๐Ÿ› Bug Fixes

  • Fixed unused parameters in handleUnauthorized function
  • Improved token refresh flow reliability
  • Enhanced error message sanitization for security