import type { NextFunction, Request, RequestHandler, Response } from 'express'; import { hashApiKey } from '../lib/crypto.js'; import { findByApiKeyHash } from '../db/integrations.dao.js'; import type { IntegrationRow } from '../types/integration.js'; declare module 'express-serve-static-core' { interface Request { integration?: IntegrationRow; } } const BEARER = /^Bearer (.+)$/; /** * Every rejection returns the same body. Distinguishing "no such key" from * "wrong key" would let a caller enumerate valid keys. */ export const requireApiKey: RequestHandler = async ( req: Request, res: Response, next: NextFunction ) => { try { const match = BEARER.exec(req.get('authorization') ?? ''); if (!match) { res.status(401).json({ error: 'Unauthorized' }); return; } const integration = await findByApiKeyHash(hashApiKey(match[1])); if (!integration) { res.status(401).json({ error: 'Unauthorized' }); return; } req.integration = integration; next(); } catch (err) { next(err); } };