From 6353c5c3398679d82416c8606ad85140d1336dfa Mon Sep 17 00:00:00 2001 From: Kmario19 Date: Wed, 2 Apr 2025 22:43:04 -0500 Subject: [PATCH 1/4] feat: add API key validation middleware and update environment configuration --- src/config/environment.ts | 1 + src/middleware/apiKeyValidator.ts | 21 +++++++++++++++++++++ src/routes/index.ts | 2 ++ 3 files changed, 24 insertions(+) create mode 100644 src/middleware/apiKeyValidator.ts diff --git a/src/config/environment.ts b/src/config/environment.ts index ebec24c..31d94e5 100644 --- a/src/config/environment.ts +++ b/src/config/environment.ts @@ -9,6 +9,7 @@ export default () => { NODE_ENV: z.enum(['development', 'production', 'test']).default('development'), MONGODB_URI: z.string().url(), TRANSACTION_DELETE_POLICY: z.enum(['keep', 'cascade', 'deny']).default('keep'), + API_KEYS: z.string().optional(), }); const env = envSchema.safeParse(process.env); diff --git a/src/middleware/apiKeyValidator.ts b/src/middleware/apiKeyValidator.ts new file mode 100644 index 0000000..9b05106 --- /dev/null +++ b/src/middleware/apiKeyValidator.ts @@ -0,0 +1,21 @@ +import type { Request, Response, NextFunction } from 'express'; + +const apiKeyValidator = (req: Request, res: Response, next: NextFunction) => { + const apiKey = req.header('x-api-key'); + + if (!process.env.API_KEYS) { + res.status(500).json({ error: 'API keys are not configured.' }); + return; + } + + const allowedKeys = process.env.API_KEYS.split(','); + + if (!apiKey || !allowedKeys.includes(apiKey)) { + res.status(401).json({ error: 'Unauthorized: Invalid API key.' }); + return; + } + + next(); +}; + +export default apiKeyValidator; diff --git a/src/routes/index.ts b/src/routes/index.ts index 7e6ba3b..af78fb7 100644 --- a/src/routes/index.ts +++ b/src/routes/index.ts @@ -1,9 +1,11 @@ import express from 'express'; import transactionRoutes from './transaction'; import accountRoutes from './account'; +import apiKeyValidator from '@/middleware/apiKeyValidator'; const app = express(); +app.use(apiKeyValidator); app.use('/transactions', transactionRoutes); app.use('/accounts', accountRoutes); From 5b10d26d840717a5b3e1eaef882ca5b0a39946a5 Mon Sep 17 00:00:00 2001 From: Kmario19 Date: Wed, 2 Apr 2025 22:43:09 -0500 Subject: [PATCH 2/4] docs: update README to include API authentication details and example request --- README.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/README.md b/README.md index 17c5283..64d49f7 100644 --- a/README.md +++ b/README.md @@ -92,6 +92,20 @@ http://localhost:/docs Replace `` with the configured port in your `.env` file. +## API Authentication + +The API is secured using API keys. Each request must include a valid API key in the `x-api-key` header. The API keys are configured in the environment variable `API_KEYS` as a comma-separated list. + +### Example Request + +Include the `x-api-key` header in your request: + +```bash +curl -X GET "http://localhost:/transactions" -H "x-api-key: YOUR_API_KEY" +``` + +Replace `` with the configured port in your `.env` file and `YOUR_API_KEY` with a valid API key. + ## Deployment The project uses GitHub Actions for CI/CD. The workflow builds, tests, and packages the application for release when tags are pushed. From 1f99e57e155f92415cb77869b0e95c200d6b0d30 Mon Sep 17 00:00:00 2001 From: Kmario19 Date: Wed, 2 Apr 2025 22:44:03 -0500 Subject: [PATCH 3/4] feat: add API key security scheme to docs BREAKING CHANGE --- swagger.json | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/swagger.json b/swagger.json index 2682108..179a165 100644 --- a/swagger.json +++ b/swagger.json @@ -636,6 +636,18 @@ } } } + }, + "securitySchemes": { + "ApiKeyAuth": { + "type": "apiKey", + "in": "header", + "name": "x-api-key" + } + } + }, + "security": [ + { + "ApiKeyAuth": [] } - } + ] } From 510331f10f0cb21272b9043b71b5ab95d02eddb4 Mon Sep 17 00:00:00 2001 From: Kmario19 Date: Wed, 2 Apr 2025 22:47:13 -0500 Subject: [PATCH 4/4] feat: update .env.example to include API keys for authentication --- .env.example | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.env.example b/.env.example index 3fb4635..957870b 100644 --- a/.env.example +++ b/.env.example @@ -9,4 +9,7 @@ MONGODB_URI=mongodb://admin:password123@localhost:27017/transaction_ledger?authS # keep: Keep transactions after account deletion # cascade: Delete transactions after account deletion # deny: Deny deletion of the account -TRANSACTION_DELETE_POLICY=keep \ No newline at end of file +TRANSACTION_DELETE_POLICY=keep + +# API keys for authentication +API_KEYS=your_api_key_1,your_api_key_2 \ No newline at end of file