Package Exports
- @sp-uvb/express
Readme
@sp-uvb/express
Express middleware for Universal Verification Broker (UVB) authentication.
Installation
npm install @sp-uvb/express
# or
yarn add @sp-uvb/express
# or
pnpm add @sp-uvb/expressQuick Start
import express from 'express';
import { uvbMiddleware, requireFactors } from '@sp-uvb/express';
const app = express();
// Apply UVB authentication to all routes
app.use(
uvbMiddleware({
tenantId: 'my-tenant',
uvbUrl: 'http://localhost:8080',
excludePaths: ['/login', '/health', '/public'],
})
);
// Access the authenticated user
app.get('/profile', (req, res) => {
const session = req.uvbSession;
res.json({
userId: session?.userId,
factors: session?.factorsVerified,
});
});
// Require specific MFA factors for sensitive routes
app.post('/admin/delete', requireFactors(['totp', 'webauthn']), (req, res) => {
res.json({ message: 'Admin action completed' });
});
app.listen(3000);API
uvbMiddleware(options)
Main authentication middleware.
Options:
tenantId(required): Your UVB tenant IDuvbUrl(optional): UVB server URL, defaults tohttp://localhost:8080apiKey(optional): API key for server-to-server authenticationsessionKey(optional): Custom key for storing session in req object, defaults touvbSessioncookieName(optional): Cookie name for session token, defaults touvb_sessionexcludePaths(optional): Array of paths to exclude from authentication, defaults to[]onError(optional): Custom error handler function
Attached to Request:
After successful authentication, req.uvbSession contains:
interface UVBSession {
userId: string;
tenantId: string;
factorsVerified: string[];
sessionId: string;
expiresAt: Date;
}requireFactors(factors: string[])
Middleware to require specific MFA factors for a route.
app.get(
'/sensitive',
uvbMiddleware({ tenantId: 'my-tenant' }),
requireFactors(['totp', 'webauthn']),
(req, res) => {
// Only accessible if user has verified both TOTP and WebAuthn
}
);getSession(req: Request)
Helper function to get the current UVB session from a request.
import { getSession } from '@sp-uvb/express';
app.get('/info', (req, res) => {
const session = getSession(req);
if (!session) {
return res.status(401).send('Not authenticated');
}
res.json({ userId: session.userId });
});Examples
Protecting Specific Routes
// Public routes
app.get('/health', (req, res) => res.json({ status: 'ok' }));
// Protected routes
app.use(
'/api',
uvbMiddleware({
tenantId: 'my-tenant',
uvbUrl: process.env.UVB_URL,
})
);
app.get('/api/data', (req, res) => {
// User is authenticated
res.json({ data: 'protected' });
});Custom Error Handling
app.use(
uvbMiddleware({
tenantId: 'my-tenant',
onError: (err, req, res, next) => {
console.error('UVB auth error:', err);
res.status(401).json({
error: 'Authentication failed',
details: err.message,
});
},
})
);Conditional MFA Requirements
app.post(
'/transfer',
uvbMiddleware({ tenantId: 'my-tenant' }),
(req, res, next) => {
const amount = req.body.amount;
// Require additional auth for large transfers
if (amount > 10000) {
return requireFactors(['totp', 'webauthn'])(req, res, next);
}
next();
},
(req, res) => {
res.json({ message: 'Transfer initiated' });
}
);TypeScript
This package includes TypeScript definitions. The Request type is automatically extended:
import { Request } from 'express';
app.get('/test', (req: Request, res) => {
// TypeScript knows about uvbSession
const userId = req.uvbSession?.userId;
});License
MIT