import { type Request, type Response, type NextFunction } from "express";
/**
* 認証設定
*/
export const AUTH_CONFIG = {
// 認証を有効にするかどうか(環境変数で制御)
enabled: process.env.AUTH_ENABLED === "true",
// APIキー(環境変数から取得、デフォルトは空文字)
apiKey: process.env.API_KEY || "",
} as const;
/**
* 認証ミドルウェア
*
* 認証が有効な場合、リクエストヘッダーの`Authorization`または`X-API-Key`から
* APIキーを取得し、設定されたAPIキーと一致するか確認します。
*
* 認証が無効な場合は、すべてのリクエストを通過させます。
*/
export function authMiddleware(
req: Request,
res: Response,
next: NextFunction
): void {
// 認証が無効な場合は通過
if (!AUTH_CONFIG.enabled) {
next();
return;
}
// APIキーが設定されていない場合はエラー
if (!AUTH_CONFIG.apiKey) {
res.status(500).json({
error: "Server configuration error: API_KEY is not set",
});
return;
}
// リクエストからAPIキーを取得
// 1. Authorizationヘッダー: "Bearer <key>" または "ApiKey <key>"
// 2. X-API-Keyヘッダー: "<key>"
const authHeader = req.headers.authorization;
const apiKeyHeader = req.headers["x-api-key"] as string | undefined;
let providedKey: string | undefined;
if (authHeader) {
// "Bearer <key>" または "ApiKey <key>" 形式をサポート
const parts = authHeader.split(" ");
if (parts.length === 2 && (parts[0] === "Bearer" || parts[0] === "ApiKey")) {
providedKey = parts[1];
} else if (parts.length === 1) {
// プレフィックスなしの場合も許可
providedKey = parts[0];
}
} else if (apiKeyHeader) {
providedKey = apiKeyHeader;
}
// APIキーが提供されていない場合
if (!providedKey) {
res.status(401).json({
error: "Authentication required",
message: "Please provide an API key via Authorization header or X-API-Key header",
});
return;
}
// APIキーが一致しない場合
if (providedKey !== AUTH_CONFIG.apiKey) {
res.status(403).json({
error: "Invalid API key",
});
return;
}
// 認証成功
next();
}