OverviewFilesCommitsIssuesDocsReleasesPeers

hyper-web-ui / lib / auth.js

56 lines · javascript ref:
/**
 * 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
}