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

@sp-uvb/elysia

v0.1.0

Published

Production-grade Elysia plugin for Universal Verification Broker (UVB) authentication

Readme

@sp-uvb/elysia

Production-grade Elysia plugin for Universal Verification Broker (UVB) authentication. Built using Elysia's Service Locator pattern for type-safe session management across your Bun application.

Features

  • 🔐 Automatic Session Validation - Validates sessions on every request
  • 🎯 Service Locator Pattern - Type-safe uvbSession access in all routes
  • 🛡️ MFA Factor Guards - Require specific authentication factors per route
  • 👤 Resource Ownership - Verify users own resources they're accessing
  • 🚀 Zero Configuration - Works out of the box with sensible defaults
  • 📊 Built-in Session Routes - Optional /uvb/session and /uvb/logout endpoints
  • 🔧 Fully Customizable - Override error handlers, customize behavior
  • 💪 TypeScript First - Complete type safety with Elysia's plugin system

Installation

bun add @sp-uvb/elysia elysia

Quick Start

Basic Setup

import { Elysia } from 'elysia';
import { uvb } from '@sp-uvb/elysia';

const app = new Elysia()
  .use(
    uvb({
      uvbUrl: process.env.UVB_URL || 'http://localhost:8080',
      tenantId: process.env.UVB_TENANT_ID || 'tenant_123',
    })
  )
  .get('/', () => 'Hello UVB!')
  .get('/profile', ({ uvbSession }) => {
    if (!uvbSession) {
      return { error: 'Not authenticated' };
    }
    return {
      userId: uvbSession.userId,
      factors: uvbSession.factorsVerified,
    };
  })
  .listen(3000);

console.log(`🦊 Elysia is running at ${app.server?.hostname}:${app.server?.port}`);

Required Authentication

import { Elysia } from 'elysia';
import { uvb, uvbGuard } from '@sp-uvb/elysia';

const app = new Elysia()
  .use(
    uvb({
      uvbUrl: process.env.UVB_URL!,
      tenantId: process.env.UVB_TENANT_ID!,
      required: true, // All routes require authentication
    })
  )
  .get('/dashboard', ({ uvbSession }) => {
    // uvbSession is guaranteed to exist when required: true
    return {
      welcome: `Hello, user ${uvbSession.userId}!`,
      sessionId: uvbSession.sessionId,
    };
  })
  .listen(3000);

Configuration Options

UvbPluginOptions

interface UvbPluginOptions {
  // Required: UVB server URL
  uvbUrl: string;

  // Required: Your tenant ID
  tenantId: string;

  // Optional: Cookie name for session token (default: 'uvb_session')
  cookieName?: string;

  // Optional: Header name for session token (default: 'x-uvb-session')
  headerName?: string;

  // Optional: Paths to exclude from authentication (default: [])
  excludePaths?: string[];

  // Optional: Require authentication on all routes (default: false)
  required?: boolean;

  // Optional: Custom error handler
  onError?: (context: Context, error: Error) => Response | Promise<Response>;

  // Optional: Custom unauthorized handler
  onUnauthorized?: (context: Context) => Response | Promise<Response>;

  // Optional: Custom insufficient factors handler
  onInsufficientFactors?: (
    context: Context,
    required: string[],
    verified: string[]
  ) => Response | Promise<Response>;
}

Session Object

The uvbSession object is automatically attached to your route context:

interface UvbSession {
  userId: string; // Unique user identifier
  tenantId: string; // Tenant identifier
  sessionId: string; // Session identifier
  factorsVerified: string[]; // List of verified authentication factors
  expiresAt: Date; // Session expiration timestamp
  metadata?: Record<string, any>; // Optional session metadata
}

Authentication Guards

Basic Guard

Require authentication for specific routes:

import { Elysia } from 'elysia';
import { uvb, uvbGuard } from '@sp-uvb/elysia';

const app = new Elysia()
  .use(
    uvb({
      uvbUrl: process.env.UVB_URL!,
      tenantId: process.env.UVB_TENANT_ID!,
    })
  )
  .get('/public', () => 'Anyone can access')
  .get(
    '/protected',
    ({ uvbSession }) => {
      return { userId: uvbSession!.userId };
    },
    {
      beforeHandle: uvbGuard(),
    }
  )
  .listen(3000);

MFA Factor Requirements

Require All Factors

import { Elysia } from 'elysia';
import { uvb, uvbRequireAllFactors } from '@sp-uvb/elysia';

const app = new Elysia()
  .use(
    uvb({
      uvbUrl: process.env.UVB_URL!,
      tenantId: process.env.UVB_TENANT_ID!,
    })
  )
  .post(
    '/transfer',
    async ({ body, uvbSession }) => {
      // User has verified password + TOTP + WebAuthn
      return {
        transfer: 'authorized',
        amount: body.amount,
        userId: uvbSession!.userId,
      };
    },
    {
      beforeHandle: uvbRequireAllFactors(['password', 'totp', 'webauthn']),
    }
  )
  .listen(3000);

Require Any Factor

import { Elysia } from 'elysia';
import { uvb, uvbRequireAnyFactor } from '@sp-uvb/elysia';

const app = new Elysia()
  .use(
    uvb({
      uvbUrl: process.env.UVB_URL!,
      tenantId: process.env.UVB_TENANT_ID!,
    })
  )
  .get(
    '/settings',
    ({ uvbSession }) => {
      return {
        userId: uvbSession!.userId,
        mfaEnabled: true,
      };
    },
    {
      beforeHandle: uvbRequireAnyFactor(['totp', 'webauthn', 'sms']),
    }
  )
  .listen(3000);

Resource Ownership Verification

Ensure users can only access their own resources:

import { Elysia } from 'elysia';
import { uvb, uvbRequireOwnership } from '@sp-uvb/elysia';

// Mock database
const posts = new Map([
  ['post_1', { id: 'post_1', title: 'Hello', authorId: 'user_123' }],
  ['post_2', { id: 'post_2', title: 'World', authorId: 'user_456' }],
]);

const app = new Elysia()
  .use(
    uvb({
      uvbUrl: process.env.UVB_URL!,
      tenantId: process.env.UVB_TENANT_ID!,
      required: true,
    })
  )
  .delete(
    '/posts/:id',
    ({ params }) => {
      posts.delete(params.id);
      return { deleted: params.id };
    },
    {
      beforeHandle: uvbRequireOwnership({
        getUserId: async ({ params }) => {
          const post = posts.get(params.id);
          if (!post) throw new Error('Post not found');
          return post.authorId;
        },
      }),
    }
  )
  .listen(3000);

Session Management Routes

Add built-in session management endpoints:

import { Elysia } from 'elysia';
import { uvb, uvbSessionRoutes } from '@sp-uvb/elysia';

const app = new Elysia()
  .use(
    uvb({
      uvbUrl: process.env.UVB_URL!,
      tenantId: process.env.UVB_TENANT_ID!,
    })
  )
  .use(
    uvbSessionRoutes({
      uvbUrl: process.env.UVB_URL!,
      tenantId: process.env.UVB_TENANT_ID!,
    })
  )
  // Adds:
  // GET  /uvb/session - Get current session info
  // POST /uvb/logout  - Revoke session and clear cookie
  .listen(3000);

Now you can:

# Get session info
curl http://localhost:3000/uvb/session \
  -H "Authorization: Bearer <session_token>"

# Logout
curl -X POST http://localhost:3000/uvb/logout \
  -H "Authorization: Bearer <session_token>"

Advanced Examples

Conditional MFA Requirements

import { Elysia } from 'elysia';
import { uvb, uvbGuard, hasAllFactors } from '@sp-uvb/elysia';

const app = new Elysia()
  .use(
    uvb({
      uvbUrl: process.env.UVB_URL!,
      tenantId: process.env.UVB_TENANT_ID!,
      required: true,
    })
  )
  .post('/api/transactions', async ({ body, uvbSession }) => {
    const amount = parseFloat(body.amount);

    // Require MFA for large transactions
    if (amount > 10000 && !hasAllFactors(uvbSession, ['totp', 'webauthn'])) {
      return new Response(
        JSON.stringify({
          error: 'MFA required for large transactions',
          required: ['totp', 'webauthn'],
          verified: uvbSession!.factorsVerified,
        }),
        {
          status: 403,
          headers: { 'Content-Type': 'application/json' },
        }
      );
    }

    return {
      transaction: 'processed',
      amount,
      userId: uvbSession!.userId,
    };
  })
  .listen(3000);

Custom Error Handlers

import { Elysia } from 'elysia';
import { uvb } from '@sp-uvb/elysia';

const app = new Elysia()
  .use(
    uvb({
      uvbUrl: process.env.UVB_URL!,
      tenantId: process.env.UVB_TENANT_ID!,
      required: true,
      onUnauthorized: (context) => {
        return new Response(
          JSON.stringify({
            error: 'Authentication required',
            message: 'Please log in to continue',
            loginUrl: '/auth/login',
          }),
          {
            status: 401,
            headers: {
              'Content-Type': 'application/json',
              'WWW-Authenticate': 'Bearer realm="UVB"',
            },
          }
        );
      },
      onError: (context, error) => {
        console.error('UVB error:', error);
        return new Response(
          JSON.stringify({
            error: 'Internal authentication error',
            requestId: crypto.randomUUID(),
          }),
          {
            status: 500,
            headers: { 'Content-Type': 'application/json' },
          }
        );
      },
    })
  )
  .listen(3000);

Path Exclusions

import { Elysia } from 'elysia';
import { uvb } from '@sp-uvb/elysia';

const app = new Elysia()
  .use(
    uvb({
      uvbUrl: process.env.UVB_URL!,
      tenantId: process.env.UVB_TENANT_ID!,
      required: true,
      excludePaths: ['/health', '/metrics', '/public', '/auth'],
    })
  )
  .get('/health', () => ({ status: 'ok' }))
  .get('/public/terms', () => 'Terms of Service...')
  .get('/dashboard', ({ uvbSession }) => {
    return { userId: uvbSession!.userId };
  })
  .listen(3000);

Multiple Authentication Schemes

import { Elysia } from 'elysia';
import { uvb } from '@sp-uvb/elysia';

const app = new Elysia()
  .use(
    uvb({
      uvbUrl: process.env.UVB_URL!,
      tenantId: process.env.UVB_TENANT_ID!,
    })
  )
  .get('/api/data', ({ uvbSession, headers }) => {
    // Try UVB session first
    if (uvbSession) {
      return {
        data: 'authenticated via UVB',
        userId: uvbSession.userId,
      };
    }

    // Fallback to API key
    const apiKey = headers['x-api-key'];
    if (apiKey && isValidApiKey(apiKey)) {
      return {
        data: 'authenticated via API key',
        apiKey: apiKey.substring(0, 8) + '...',
      };
    }

    return new Response(JSON.stringify({ error: 'Authentication required' }), {
      status: 401,
      headers: { 'Content-Type': 'application/json' },
    });
  })
  .listen(3000);

function isValidApiKey(key: string): boolean {
  // Your API key validation logic
  return key.startsWith('sk_');
}

WebSocket with Authentication

import { Elysia } from 'elysia';
import { uvb } from '@sp-uvb/elysia';

const app = new Elysia()
  .use(
    uvb({
      uvbUrl: process.env.UVB_URL!,
      tenantId: process.env.UVB_TENANT_ID!,
    })
  )
  .ws('/ws', {
    open(ws) {
      const session = ws.data.uvbSession;
      if (!session) {
        ws.close(1008, 'Authentication required');
        return;
      }
      console.log(`User ${session.userId} connected`);
    },
    message(ws, message) {
      const session = ws.data.uvbSession;
      ws.send({
        echo: message,
        userId: session?.userId,
        timestamp: new Date().toISOString(),
      });
    },
    close(ws) {
      console.log('Client disconnected');
    },
  })
  .listen(3000);

Helper Functions

Check Individual Factor

import { hasFactor } from '@sp-uvb/elysia';

app.get('/settings/mfa', ({ uvbSession }) => {
  return {
    totpEnabled: hasFactor(uvbSession, 'totp'),
    webauthnEnabled: hasFactor(uvbSession, 'webauthn'),
    smsEnabled: hasFactor(uvbSession, 'sms'),
  };
});

Check All Factors

import { hasAllFactors } from '@sp-uvb/elysia';

app.get('/admin/panel', ({ uvbSession }) => {
  if (!hasAllFactors(uvbSession, ['password', 'totp', 'webauthn'])) {
    return new Response('Admin requires full MFA', { status: 403 });
  }
  return { admin: 'panel' };
});

Check Any Factor

import { hasAnyFactor } from '@sp-uvb/elysia';

app.get('/settings', ({ uvbSession }) => {
  const hasMFA = hasAnyFactor(uvbSession, ['totp', 'webauthn', 'sms']);
  return {
    mfaEnabled: hasMFA,
    message: hasMFA ? 'MFA is active' : 'Enable MFA for better security',
  };
});

Real-World Patterns

E-commerce API

import { Elysia } from 'elysia';
import { uvb, uvbGuard, uvbRequireAllFactors, uvbRequireOwnership } from '@sp-uvb/elysia';

// Mock database
const orders = new Map<string, { id: string; userId: string; total: number }>();

const app = new Elysia()
  .use(
    uvb({
      uvbUrl: process.env.UVB_URL!,
      tenantId: process.env.UVB_TENANT_ID!,
    })
  )

  // Public product listing
  .get('/products', () => {
    return [
      { id: 'prod_1', name: 'Widget', price: 29.99 },
      { id: 'prod_2', name: 'Gadget', price: 49.99 },
    ];
  })

  // Cart requires authentication
  .post(
    '/cart',
    ({ body, uvbSession }) => {
      return {
        cart: body,
        userId: uvbSession!.userId,
      };
    },
    {
      beforeHandle: uvbGuard(),
    }
  )

  // Checkout requires MFA
  .post(
    '/checkout',
    async ({ body, uvbSession }) => {
      const orderId = crypto.randomUUID();
      orders.set(orderId, {
        id: orderId,
        userId: uvbSession!.userId,
        total: body.total,
      });
      return { orderId, status: 'confirmed' };
    },
    {
      beforeHandle: uvbRequireAllFactors(['password', 'totp']),
    }
  )

  // View order (must be owner)
  .get(
    '/orders/:id',
    ({ params }) => {
      const order = orders.get(params.id);
      if (!order) {
        return new Response('Order not found', { status: 404 });
      }
      return order;
    },
    {
      beforeHandle: [
        uvbGuard(),
        uvbRequireOwnership({
          getUserId: async ({ params }) => {
            const order = orders.get(params.id);
            if (!order) throw new Error('Order not found');
            return order.userId;
          },
        }),
      ],
    }
  )

  .listen(3000);

Multi-Tenant SaaS

import { Elysia } from 'elysia';
import { uvb, uvbGuard } from '@sp-uvb/elysia';

interface User {
  id: string;
  tenantId: string;
  role: 'admin' | 'member';
}

const users = new Map<string, User>([
  ['user_1', { id: 'user_1', tenantId: 'tenant_123', role: 'admin' }],
  ['user_2', { id: 'user_2', tenantId: 'tenant_123', role: 'member' }],
  ['user_3', { id: 'user_3', tenantId: 'tenant_456', role: 'admin' }],
]);

const app = new Elysia()
  .use(
    uvb({
      uvbUrl: process.env.UVB_URL!,
      tenantId: process.env.UVB_TENANT_ID!,
      required: true,
    })
  )
  .derive(({ uvbSession }) => {
    const user = users.get(uvbSession!.userId);
    return { user };
  })

  // Tenant-scoped data access
  .get('/api/workspace/:workspaceId', ({ params, user, uvbSession }) => {
    if (!user) {
      return new Response('User not found', { status: 404 });
    }

    // Verify tenant access
    if (user.tenantId !== uvbSession!.tenantId) {
      return new Response('Forbidden', { status: 403 });
    }

    return {
      workspaceId: params.workspaceId,
      tenantId: user.tenantId,
      role: user.role,
    };
  })

  // Admin-only endpoint
  .post('/api/workspace/:workspaceId/settings', ({ params, user }) => {
    if (!user || user.role !== 'admin') {
      return new Response('Admin access required', { status: 403 });
    }

    return {
      updated: true,
      workspaceId: params.workspaceId,
    };
  })

  .listen(3000);

Social Media API

import { Elysia } from 'elysia';
import { uvb, uvbGuard, uvbRequireOwnership, uvbRequireAllFactors } from '@sp-uvb/elysia';

interface Post {
  id: string;
  authorId: string;
  content: string;
  visibility: 'public' | 'private';
}

const posts = new Map<string, Post>();

const app = new Elysia()
  .use(
    uvb({
      uvbUrl: process.env.UVB_URL!,
      tenantId: process.env.UVB_TENANT_ID!,
    })
  )

  // Public feed (no auth required)
  .get('/feed', () => {
    return Array.from(posts.values())
      .filter((p) => p.visibility === 'public')
      .slice(0, 20);
  })

  // Create post (auth required)
  .post(
    '/posts',
    ({ body, uvbSession }) => {
      const postId = crypto.randomUUID();
      const post: Post = {
        id: postId,
        authorId: uvbSession!.userId,
        content: body.content,
        visibility: body.visibility || 'public',
      };
      posts.set(postId, post);
      return post;
    },
    {
      beforeHandle: uvbGuard(),
    }
  )

  // Edit post (must be author)
  .patch(
    '/posts/:id',
    ({ params, body }) => {
      const post = posts.get(params.id);
      if (!post) {
        return new Response('Post not found', { status: 404 });
      }
      post.content = body.content;
      return post;
    },
    {
      beforeHandle: uvbRequireOwnership({
        getUserId: async ({ params }) => {
          const post = posts.get(params.id);
          if (!post) throw new Error('Post not found');
          return post.authorId;
        },
      }),
    }
  )

  // Delete post (must be author + MFA)
  .delete(
    '/posts/:id',
    ({ params }) => {
      posts.delete(params.id);
      return { deleted: params.id };
    },
    {
      beforeHandle: [
        uvbRequireAllFactors(['password', 'totp']),
        uvbRequireOwnership({
          getUserId: async ({ params }) => {
            const post = posts.get(params.id);
            if (!post) throw new Error('Post not found');
            return post.authorId;
          },
        }),
      ],
    }
  )

  .listen(3000);

Testing

Unit Testing

import { describe, expect, it } from 'bun:test';
import { Elysia } from 'elysia';
import { uvb, uvbGuard } from '@sp-uvb/elysia';

describe('UVB Authentication', () => {
  it('should allow public access without auth', async () => {
    const app = new Elysia()
      .use(
        uvb({
          uvbUrl: 'http://localhost:8080',
          tenantId: 'test_tenant',
        })
      )
      .get('/public', () => 'public');

    const response = await app.handle(new Request('http://localhost/public'));
    expect(response.status).toBe(200);
    expect(await response.text()).toBe('public');
  });

  it('should block protected routes without auth', async () => {
    const app = new Elysia()
      .use(
        uvb({
          uvbUrl: 'http://localhost:8080',
          tenantId: 'test_tenant',
        })
      )
      .get(
        '/protected',
        ({ uvbSession }) => {
          return { userId: uvbSession!.userId };
        },
        {
          beforeHandle: uvbGuard(),
        }
      );

    const response = await app.handle(new Request('http://localhost/protected'));
    expect(response.status).toBe(401);
  });

  it('should allow access with valid session', async () => {
    const app = new Elysia()
      .use(
        uvb({
          uvbUrl: 'http://localhost:8080',
          tenantId: 'test_tenant',
        })
      )
      .get(
        '/profile',
        ({ uvbSession }) => {
          return { userId: uvbSession!.userId };
        },
        {
          beforeHandle: uvbGuard(),
        }
      );

    const response = await app.handle(
      new Request('http://localhost/profile', {
        headers: {
          Authorization: 'Bearer valid_session_token',
        },
      })
    );

    expect(response.status).toBe(200);
    const data = await response.json();
    expect(data.userId).toBeDefined();
  });
});

Integration Testing

import { describe, expect, it, beforeAll, afterAll } from 'bun:test';
import { Elysia } from 'elysia';
import { uvb, uvbRequireAllFactors } from '@sp-uvb/elysia';

let app: Elysia;
let sessionToken: string;

beforeAll(async () => {
  // Start app
  app = new Elysia()
    .use(
      uvb({
        uvbUrl: process.env.UVB_URL!,
        tenantId: process.env.UVB_TENANT_ID!,
      })
    )
    .get('/data', ({ uvbSession }) => ({ data: 'test' }), {
      beforeHandle: uvbRequireAllFactors(['password', 'totp']),
    })
    .listen(3001);

  // Create test session
  const authResponse = await fetch(`${process.env.UVB_URL}/api/v1/auth/login`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      tenant_id: process.env.UVB_TENANT_ID,
      username: '[email protected]',
      password: 'password',
    }),
  });
  const authData = await authResponse.json();
  sessionToken = authData.session_token;
});

afterAll(() => {
  app.stop();
});

describe('MFA Requirements', () => {
  it('should block access without MFA', async () => {
    const response = await fetch('http://localhost:3001/data', {
      headers: { Authorization: `Bearer ${sessionToken}` },
    });
    expect(response.status).toBe(403);
  });

  it('should allow access with MFA', async () => {
    // Complete MFA challenge
    await fetch(`${process.env.UVB_URL}/api/v1/mfa/verify`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        session_token: sessionToken,
        factor: 'totp',
        code: '123456',
      }),
    });

    const response = await fetch('http://localhost:3001/data', {
      headers: { Authorization: `Bearer ${sessionToken}` },
    });
    expect(response.status).toBe(200);
  });
});

API Reference

Main Plugin

uvb(options: UvbPluginOptions)

Main authentication plugin. Adds session validation and attaches uvbSession to context.

Guards

uvbGuard(options?: UvbGuardOptions)

Basic authentication guard. Returns 401 if not authenticated.

uvbRequireFactors(factors: string[], options?: UvbGuardOptions)

Require specific authentication factors. Returns 403 if factors not verified.

uvbRequireAllFactors(factors: string[], options?: UvbGuardOptions)

Require all specified factors. Returns 403 if any factor missing.

uvbRequireAnyFactor(factors: string[], options?: UvbGuardOptions)

Require at least one of the specified factors. Returns 403 if no factors match.

uvbRequireOwnership(options: UvbOwnershipOptions)

Verify user owns a resource. Returns 403 if not owner.

Utilities

uvbSessionRoutes(options: { uvbUrl: string; tenantId: string })

Add session management routes:

  • GET /uvb/session - Get current session
  • POST /uvb/logout - Revoke session

hasFactor(session: UvbSession | null, factor: string): boolean

Check if session has specific factor.

hasAllFactors(session: UvbSession | null, factors: string[]): boolean

Check if session has all specified factors.

hasAnyFactor(session: UvbSession | null, factors: string[]): boolean

Check if session has any of the specified factors.

Best Practices

1. Environment Variables

Always use environment variables for sensitive configuration:

const app = new Elysia().use(
  uvb({
    uvbUrl: process.env.UVB_URL!,
    tenantId: process.env.UVB_TENANT_ID!,
  })
);

2. Path Exclusions

Exclude health checks and public endpoints:

.use(uvb({
  // ...
  excludePaths: ['/health', '/metrics', '/public'],
}))

3. Custom Error Handlers

Provide user-friendly error messages:

.use(uvb({
  // ...
  onUnauthorized: () => new Response(
    JSON.stringify({ error: 'Please log in' }),
    { status: 401, headers: { 'Content-Type': 'application/json' } }
  ),
}))

4. Factor Requirements

Use appropriate MFA levels for sensitive operations:

// Low risk: basic auth
.get('/profile', handler, { beforeHandle: uvbGuard() })

// Medium risk: any MFA
.post('/settings', handler, {
  beforeHandle: uvbRequireAnyFactor(['totp', 'webauthn'])
})

// High risk: all factors
.post('/delete-account', handler, {
  beforeHandle: uvbRequireAllFactors(['password', 'totp', 'webauthn'])
})

5. Session Expiration

Check session expiration in your application:

.get('/data', ({ uvbSession }) => {
  if (uvbSession && uvbSession.expiresAt < new Date()) {
    return new Response('Session expired', { status: 401 })
  }
  return { data: 'value' }
})

Troubleshooting

Session Not Found

Problem: uvbSession is always null

Solutions:

  • Check UVB server is running and accessible
  • Verify uvbUrl and tenantId are correct
  • Ensure session token is being sent (cookie or header)
  • Check session hasn't expired

401 Errors

Problem: All routes return 401

Solutions:

  • Set required: false for optional auth
  • Add public paths to excludePaths
  • Verify session token is valid

403 Errors

Problem: Factor requirements failing

Solutions:

  • Check user has completed required MFA factors
  • Use hasAllFactors() to debug which factors are verified
  • Consider using uvbRequireAnyFactor instead of uvbRequireAllFactors

TypeScript Errors

Problem: uvbSession type errors

Solutions:

  • Ensure @sp-uvb/elysia is properly installed
  • Use guards to guarantee session exists
  • Check for null: if (!uvbSession) return ...

Migration Guide

From Custom Elysia Middleware

Before:

.derive(async ({ cookie }) => {
  const token = cookie.session
  const session = await validateWithUvb(token)
  return { session }
})

After:

.use(uvb({
  uvbUrl: process.env.UVB_URL!,
  tenantId: process.env.UVB_TENANT_ID!,
}))
// Access via context.uvbSession

From Manual Factor Checks

Before:

.post('/transfer', async ({ session }) => {
  if (!session.factors.includes('totp')) {
    throw new Error('TOTP required')
  }
  // ...
})

After:

.post('/transfer', handler, {
  beforeHandle: uvbRequireAllFactors(['totp'])
})

License

MIT

Support

For issues and questions: