/**
* Auth Middleware — Bearer token extraction from HTTP requests
*
* Web-layer concern only. Does NOT handle challenge-response or
* signature verification — that belongs in hyper-identity.
*/
/**
* Create auth middleware for routes
*
* @param {Object} opts
* @param {Object} opts.registry — Hyperbee for token storage
* @param {boolean} opts.required — reject if not authenticated (default: false)
* @returns {Function} middleware(req, res) → { userId, token } or null
*/
export function authMiddleware (opts = {}) {
return async function (req, res) {
const token = extractToken(req)
if (!token) {
if (opts.required) {
res.writeHead(401, { 'Content-Type': 'application/json' })
res.end(JSON.stringify({ error: 'Authentication required' }))
return null
}
req.auth = null
return null
}
if (opts.registry) {
const entry = await opts.registry.get(`token:${token}`)
if (!entry || entry.value.expiresAt < Date.now()) {
if (opts.required) {
res.writeHead(401, { 'Content-Type': 'application/json' })
res.end(JSON.stringify({ error: 'Invalid or expired token' }))
return null
}
req.auth = null
return null
}
req.auth = entry.value
return entry.value
}
req.auth = { token }
return { token }
}
}
function extractToken (req) {
const auth = req.headers.authorization
if (!auth) return null
if (auth.startsWith('Bearer ')) return auth.slice(7)
return null
}