4f6aff32ab
continuous-integration/drone/push Build is passing
- API Key Middleware für alle /api/ Endpoints (X-API-Key, Bearer, Query) - API Key Management Routes (generate, revoke, status) - MCP Tools erweitert: 12 Tools (war 3) inkl. bulk ops, dashboard, search - Audit Logging für alle API/MCP Aktionen - docs/API-REFERENCE.md - vollständige API Dokumentation - docs/ARCHITECTURE.md - Architektur-Übersicht - Vorbereitung für NotiBot-Integration
66 lines
1.8 KiB
TypeScript
66 lines
1.8 KiB
TypeScript
/**
|
|
* API Key Authentication Middleware
|
|
*
|
|
* Allows external tools (like NotiBot) to authenticate via API key
|
|
* instead of session cookies. Supports:
|
|
* - Header: X-API-Key: <key>
|
|
* - Header: Authorization: Bearer <key>
|
|
* - Query param: ?apiKey=<key>
|
|
*
|
|
* If an API key is present and valid, the request is authenticated
|
|
* as that user (req.user is set, req.isAuthenticated() returns true).
|
|
* If no API key is present, falls through to normal session auth.
|
|
*/
|
|
|
|
import { Request, Response, NextFunction } from "express";
|
|
import { storage } from "./storage.js";
|
|
import { User } from "../shared/schema.js";
|
|
|
|
export function apiKeyAuth() {
|
|
return async (req: Request, _res: Response, next: NextFunction) => {
|
|
// Skip if already authenticated via session
|
|
if (req.isAuthenticated && req.isAuthenticated()) {
|
|
return next();
|
|
}
|
|
|
|
// Extract API key from various sources
|
|
let apiKey: string | undefined;
|
|
|
|
// 1. X-API-Key header
|
|
const xApiKey = req.headers["x-api-key"];
|
|
if (typeof xApiKey === "string") {
|
|
apiKey = xApiKey;
|
|
}
|
|
|
|
// 2. Authorization: Bearer <key>
|
|
if (!apiKey) {
|
|
const auth = req.headers["authorization"];
|
|
if (typeof auth === "string" && auth.startsWith("Bearer ")) {
|
|
apiKey = auth.substring(7);
|
|
}
|
|
}
|
|
|
|
// 3. Query parameter
|
|
if (!apiKey && typeof req.query.apiKey === "string") {
|
|
apiKey = req.query.apiKey;
|
|
}
|
|
|
|
if (!apiKey) {
|
|
return next(); // No API key, fall through to session auth
|
|
}
|
|
|
|
try {
|
|
const user = await storage.getUserByApiKey(apiKey);
|
|
if (user && user.isActive) {
|
|
// Attach user to request (mimics passport behavior)
|
|
(req as any).user = user;
|
|
(req as any).isAuthenticated = () => true;
|
|
}
|
|
} catch (err) {
|
|
console.error("[API Key Auth] Error:", err);
|
|
}
|
|
|
|
next();
|
|
};
|
|
}
|