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 🙏

© 2026 – Pkg Stats / Ryan Hefner

org.inovus.unified-auth

v0.8.0

Published

A unified authentication library that automatically adapts to your environment, providing simple localStorage-based authentication for development and multi-tenant cookie-based SSO for production.

Readme

org.inovus.unified-auth

A unified authentication library that automatically adapts to your environment, providing simple localStorage-based authentication for development and multi-tenant cookie-based SSO for production.

Overview

unified-auth automatically detects your environment and uses the appropriate authentication strategy:

  • localStorage Mode (Development/WebContainer): Simple authentication with login UI, perfect for local development and web containers
  • cookieSession Mode (Production): Multi-tenant SSO using cookies and sessionStorage, designed for production environments

The library seamlessly switches between modes based on where your application is running - no configuration needed. In development, you can optionally override the mode using the mode prop on AuthProvider.

Features

localStorage Mode

  • ✅ Login UI component included
  • ✅ Simple localStorage-based token storage
  • ✅ Works on localhost and web containers
  • /api relative URLs for proxy support
  • ✅ Direct login() method for user authentication

cookieSession Mode

  • ✅ Multi-tenant SSO support
  • ✅ Cookie-based authentication (reads existing auth)
  • ✅ Cross-subdomain authentication
  • ✅ Automatic tenant discovery and switching
  • ✅ SessionStorage + Cookies storage strategy
  • ✅ Automatic token refresh with fallback tenants

Shared Features

  • ✅ React Context API integration (AuthProvider, useAuth)
  • ✅ Protected route component
  • ✅ Type-safe with TypeScript
  • ✅ Automatic token refresh
  • ✅ Session management

Installation

npm install org.inovus.unified-auth

Quick Start

1. Wrap Your App with AuthProvider

import { AuthProvider } from 'org.inovus.unified-auth';

function App() {
  return (
    <AuthProvider>
      <YourApp />
    </AuthProvider>
  );
}

With mode override (development only):

// Force localStorage mode in development
<AuthProvider mode="local">
  <YourApp />
</AuthProvider>

// Force cookieSession mode in development (for testing)
<AuthProvider mode="cookie">
  <YourApp />
</AuthProvider>

// Auto-detect (default)
<AuthProvider>
  <YourApp />
</AuthProvider>

The library automatically:

  • Detects your environment (localhost/webcontainer vs production)
  • Uses localStorage mode for development (unless mode prop overrides it)
  • Uses cookieSession mode for production (mode prop is ignored in production)
  • Initialises authentication state

2. Use Authentication in Components

import { useAuth } from 'org.inovus.unified-auth';

function MyComponent() {
  const { user, isAuthenticated, isLoading, logout } = useAuth();

  if (isLoading) return <div>Loading...</div>;
  if (!isAuthenticated) return <div>Please log in</div>;

  return (
    <div>
      <h1>Welcome, {user?.fullName}</h1>
      <button onClick={logout}>Logout</button>
    </div>
  );
}

3. Protect Routes

import { ProtectedRoute } from 'org.inovus.unified-auth';

function App() {
  return (
    <Routes>
      <Route path="/login" element={<LoginPage />} />
      <Route
        path="/dashboard"
        element={
          <ProtectedRoute>
            <Dashboard />
          </ProtectedRoute>
        }
      />
    </Routes>
  );
}

Environment Detection

The library automatically detects your environment using window.location.hostname:

localStorage Mode (Development)

Returns true for:

  • localhost
  • 127.0.0.1
  • *.webcontainer.io
  • *.webcontainer-api.io
  • *.fly.dev

cookieSession Mode (Production)

Returns false for all other domains (e.g., *.totum.surgery)

Mode Override (Development Only)

In development (localhost/webcontainer), you can override the automatic detection using the mode prop:

// Force localStorage mode (default in dev)
<AuthProvider mode="local">
  <App />
</AuthProvider>

// Force cookieSession mode (for testing production mode locally)
<AuthProvider mode="cookie">
  <App />
</AuthProvider>

Note: In production (non-localhost), the mode prop is ignored and cookieSession mode is always used.

Usage Modes

localStorage Mode - Development

When running on localhost or web containers, the library uses localStorage mode:

Features

  • Has login() method for direct authentication
  • Stores tokens in localStorage
  • Uses /api relative URLs (requires proxy setup in dev server)
  • Includes LoginPage component

Proxy Setup Required

Important: localStorage mode requires a proxy configuration in your development server to route /api requests to your backend. See Configuration section for details.

Example: Login Flow

import { useAuth, LoginPage } from 'org.inovus.unified-auth';

// Use the built-in LoginPage component
function App() {
  return (
    <Routes>
      <Route path="/login" element={<LoginPage />} />
      {/* other routes */}
    </Routes>
  );
}

// Or implement custom login
function CustomLogin() {
  const { login, isLoading } = useAuth();

  const handleLogin = async (email: string, password: string) => {
    try {
      await login({ login: email, password });
      // User is now authenticated
    } catch (error) {
      console.error('Login failed:', error);
    }
  };

  // ... your login form
}

AuthContext API (localStorage Mode)

interface AuthContextType {
  user: ServiceUser | null;
  isAuthenticated: boolean;
  isLoading: boolean;
  isLocal: boolean; // Always true in localStorage mode
  authMode: "local" | "cookie"; // Always "local" in localStorage mode
  login: (request: LoginRequest) => Promise<LoginResponse>;
  logout: () => void;
}

cookieSession Mode - Production

When running in production, the library uses cookieSession mode. You can also force this mode in development using mode="cookie":

Features

  • Reads authentication from cookies (set by provider apps)
  • Multi-tenant support
  • Automatic tenant discovery
  • Tenant switching capability
  • No login() method (auth handled by provider apps)

How It Works

  1. Consumer Pattern: This app reads auth from cookies set by provider apps
  2. Automatic Discovery: Discovers all available tenants from cookies
  3. Tenant Selection: Selects best tenant (query param ?as=tenant, single tenant, or redirects)
  4. Session Management: Creates sessionStorage per tab with tokens
  5. Token Refresh: Automatic refresh with fallback to alternative tenants

Example: Multi-Tenant Usage

import { useAuth } from 'org.inovus.unified-auth';

function UserProfile() {
  const {
    user,
    currentTenant,
    availableTenants,
    logout,
    logoutAllTenants
  } = useAuth();

  return (
    <div>
      <h2>Profile</h2>
      <p>User: {user?.fullName}</p>
      <p>Current Tenant: {currentTenant}</p>
      <p>Available Tenants: {availableTenants.join(", ")}</p>

      <button onClick={logout}>Logout Current Tenant</button>
      <button onClick={logoutAllTenants}>Logout All Tenants</button>
    </div>
  );
}

AuthContext API (cookieSession Mode)

interface AuthContextType {
  user: User | null;
  isAuthenticated: boolean;
  isLoading: boolean;
  isLocal: boolean; // Always false in cookieSession mode
  authMode: "local" | "cookie"; // Always "cookie" in cookieSession mode
  currentTenant: string;
  availableTenants: string[];
  logout: () => void;
  logoutAllTenants: () => void;
}

Note: switchTenant() is available on authService but not exposed via the React context. Use authService.switchTenant() directly if needed.

API Reference

AuthService

localStorage Mode Methods

// Login with email and password
await authService.login(email: string, password: string): Promise<LoginResponse>

// Check authentication status
authService.isAuthenticated(): boolean

// Get current user (without tokens)
authService.getUser(): User | null

// Get ServiceUser (with tokens)
authService.getServiceUser(): ServiceUser | null

// Get access token
authService.getAccessToken(): string | null

// Logout
authService.logout(): void

// Make authenticated fetch request
authService.authFetch(url: string, options?: RequestInit): Promise<Response>

// Refresh token
authService.refreshToken(): Promise<boolean>

cookieSession Mode Methods

// Initialise app (refresh tokens if needed)
await authService.initializeApp(): Promise<boolean>

// Get current user
authService.getUser(): User | null

// Get current tenant
authService.getCurrentTenant(): string

// Get all available tenants
authService.getAvailableTenants(): string[]

// Switch to different tenant (private - not exposed via React context)
authService.switchTenant(tenantName: string): boolean

// Check authentication
authService.isAuthenticated(): boolean

// Make authenticated request (axios)
authService.request(url: string, options?: AxiosRequestConfig): Promise<AxiosResponse>

// Fetch auth session (with token refresh)
authService.fetchAuthSession(options?: { forceRefresh?: boolean }): Promise<SessionTokens | null>

// Redirect to main app
authService.redirectToMainApp(): void

// Logout current tenant
authService.logout(): void

// Logout all tenants
authService.logoutAllTenants(): void

React Hooks

useAuth()

Returns the authentication context for the current mode.

localStorage Mode:

const { 
  user, 
  isAuthenticated, 
  isLoading, 
  isLocal,        // Always true
  authMode,       // Always "local"
  login, 
  logout 
} = useAuth();

cookieSession Mode:

const {
  user,
  isAuthenticated,
  isLoading,
  isLocal,           // Always false
  authMode,          // Always "cookie"
  currentTenant,
  availableTenants,
  logout,
  logoutAllTenants
} = useAuth();

Components

AuthProvider

Main authentication provider component.

Props:

  • children: ReactNode - Your app component tree
  • mode?: "auto" | "local" | "cookie" - Authentication mode (development only)
    • "auto" (default) - Automatically detect based on environment
    • "local" - Force localStorage mode (dev/webcontainer style)
    • "cookie" - Force cookieSession mode (production/multi-tenant)

Note: In production (non-localhost), mode prop is ignored and cookieSession is always used.

import { AuthProvider } from 'org.inovus.unified-auth';

// Default (auto-detect)
<AuthProvider>
  <App />
</AuthProvider>

// Override in development
<AuthProvider mode="local">
  <App />
</AuthProvider>

LoginPage

Built-in login form component (localStorage mode only).

import { LoginPage } from 'org.inovus.unified-auth';

<Route path="/login" element={<LoginPage />} />

ProtectedRoute

Wraps routes that require authentication.

Behavior:

  • localStorage mode: Renders LoginPage directly when not authenticated (no redirect)
  • cookieSession mode: Redirects to /login when not authenticated
import { ProtectedRoute } from 'org.inovus.unified-auth';

<ProtectedRoute>
  <YourProtectedComponent />
</ProtectedRoute>

Types

ServiceUser

Complete user data including sensitive tokens:

interface ServiceUser {
  userId: string;
  email?: string;
  fullName?: string;
  role?: string;
  roleGroups?: string[];
  systemId?: string | null;
  accessToken: string | null;
  idToken: string | null;
  refreshToken: string;
}

User

Public user data (tokens removed):

type User = Omit<ServiceUser, 'accessToken' | 'refreshToken' | 'idToken'>;

LoginRequest

interface LoginRequest {
  login: string;
  password: string;
}

LoginResponse

interface LoginResponse {
  value: ServiceUser;
  errors: any[];
  warnings: any[];
}

Architecture

Runtime Detection Flow

Import Package
    ↓
detectIsLocal() checks window.location.hostname
    ↓
    ├─→ localhost/webcontainer.io/fly.dev (Development)
    │       ↓
    │   Check mode prop (if provided)
    │       ├─→ mode="local" → localStorage Mode
    │       ├─→ mode="cookie" → cookieSession Mode
    │       └─→ mode="auto" (default) → localStorage Mode
    │
    │   localStorage Mode:
    │   - Uses authService.localStorage
    │   - Uses AuthProvider.localStorage
    │   - Has login() method
    │
    │   cookieSession Mode:
    │   - Uses authService.cookieSession
    │   - Uses AuthProvider.cookieSession
    │   - Multi-tenant SSO
    │
    └─→ Production domains
            ↓
        cookieSession Mode (mode prop ignored)
        - Uses authService.cookieSession
        - Uses AuthProvider.cookieSession
        - Multi-tenant SSO

Storage Strategies

localStorage Mode:

  • localStorage: All tokens (accessToken, refreshToken, idToken)
  • localStorage: User data (without tokens)

cookieSession Mode:

  • Cookies: Refresh token + baseDomain (cross-subdomain SSO)
  • sessionStorage: Access token, ID token, user data (per-tab)

Migration Guide

From local-auth-public

The library maintains API compatibility. You can continue using:

import { AuthProvider, useAuth, LoginPage } from 'org.inovus.unified-auth';

// Same usage
const { login, user, logout } = useAuth();
await login({ login: email, password });

From tenant-auth

The library maintains API compatibility. You can continue using:

import { AuthProvider, useAuth } from 'org.inovus.unified-auth';

// Same usage
const { currentTenant, availableTenants } = useAuth();

Configuration

Proxy Setup for localStorage Mode (Development)

When using localStorage mode (localhost/webcontainer), you need to configure a proxy for API calls. The library uses relative /api URLs, so configure your dev server to proxy these requests.

Vite Configuration

// vite.config.js
export default {
  server: {
    proxy: {
      "/api": {
        target: "https://example.website.surgery", // Your API server
        changeOrigin: true,
        secure: true,
      },
    },
  },
};

How It Works

  1. Library makes request to /api/Account/Login
  2. Vite dev server intercepts /api/* requests
  3. Proxies to https://example.website.surgery/api/Account/Login
  4. Response is returned to the library

This works automatically - no code changes needed in the library!

Environment Variables

For Local Development (cookieSession mode)

If using cookieSession mode locally, you can set:

LOCAL_API_PORT=9000
LOCAL_TENANT_APP_PORT=3000

These are used when detectIsLocal() returns true but you're using cookieSession mode.

Development

# Install dependencies
npm install

# Build
npm run build

# Run tests
npm test

# Format code
npm run format

# Lint
npm run lint

Building the Package

npm run build

Outputs to dist/:

  • index.cjs - CommonJS bundle
  • index.mjs - ES Module bundle
  • index.d.ts - TypeScript definitions
  • unified-auth.css - Tailwind CSS styles

Testing

The library includes tests from tenant-auth. Run with:

npm test

License

MIT

Support

For issues and questions, please open an issue in the repository.