feat: API Key Auth + erweiterte MCP Tools + Dokumentation
continuous-integration/drone/push Build is passing
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
This commit is contained in:
@@ -0,0 +1,65 @@
|
||||
/**
|
||||
* 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();
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user