42 lines
1.0 KiB
TypeScript
42 lines
1.0 KiB
TypeScript
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);
|
|
}
|
|
};
|