From 41ca4013e394d454f1d9b97b873b908a002d36b4 Mon Sep 17 00:00:00 2001 From: Rory& Date: Sat, 31 May 2025 20:29:26 +0200 Subject: Generate jwt secrets --- src/api/routes/auth/registerRoute.js | 2 +- src/api/routes/statusRoute.js | 2 +- src/api/start.js | 2 ++ src/db/db.js | 1 + src/db/schemas/user.js | 2 +- src/util/index.js | 1 + src/util/jwtUtils.js | 63 ++++++++++++++++++++++++++++++++++++ src/util/secretUtils.js | 3 +- 8 files changed, 72 insertions(+), 4 deletions(-) create mode 100644 src/util/jwtUtils.js (limited to 'src') diff --git a/src/api/routes/auth/registerRoute.js b/src/api/routes/auth/registerRoute.js index 8ad4f07..f2befd8 100644 --- a/src/api/routes/auth/registerRoute.js +++ b/src/api/routes/auth/registerRoute.js @@ -1,4 +1,4 @@ -import { User } from '#db/index.js'; +import { DbUser } from '#db/index.js'; export const registerRoute = { route: '/auth/register', diff --git a/src/api/routes/statusRoute.js b/src/api/routes/statusRoute.js index 41208a4..5c3231b 100644 --- a/src/api/routes/statusRoute.js +++ b/src/api/routes/statusRoute.js @@ -1,4 +1,4 @@ -import { User } from '#db/schemas/user.js'; +import { DbUser } from '#db/index.js'; export const statusRoute = { route: '/status', diff --git a/src/api/start.js b/src/api/start.js index 6aa4567..6f57afd 100644 --- a/src/api/start.js +++ b/src/api/start.js @@ -2,12 +2,14 @@ import express from 'express'; import { registerRoutes } from './routes.js'; import { useCors, useLogging } from './middlewares/index.js'; import { initDb } from '#db/index.js'; +import {initJwt} from "#util/index.js"; const app = express(); const PORT = process.env.PORT ?? 3000; const logRequests = process.env['LOG_REQUESTS'] ?? '-'; await initDb(); +await initJwt(); // Configure Express app.use(express.json()); diff --git a/src/db/db.js b/src/db/db.js index 9a7b50e..b9a425c 100644 --- a/src/db/db.js +++ b/src/db/db.js @@ -3,6 +3,7 @@ import { readSecret } from '#util/secretUtils.js'; export async function initDb() { const connectionString = await readSecret( + "MongoDB connection string", process.env['DATABASE_SECRET_PATH'] ); try { diff --git a/src/db/schemas/user.js b/src/db/schemas/user.js index 22856b2..1a7e048 100644 --- a/src/db/schemas/user.js +++ b/src/db/schemas/user.js @@ -23,7 +23,7 @@ export const userSchema = new Schema({ }, type: { type: String, - enum: ['user', 'admin'], + enum: ['user', 'monitor', 'admin'], default: 'user' }, createdAt: { diff --git a/src/util/index.js b/src/util/index.js index 6b51d7b..e5f345c 100644 --- a/src/util/index.js +++ b/src/util/index.js @@ -1 +1,2 @@ export * from './secretUtils.js'; +export * from './jwtUtils.js'; \ No newline at end of file diff --git a/src/util/jwtUtils.js b/src/util/jwtUtils.js new file mode 100644 index 0000000..115c9c5 --- /dev/null +++ b/src/util/jwtUtils.js @@ -0,0 +1,63 @@ +import {existsSync} from 'fs'; +import {readFile, writeFile} from "node:fs/promises"; +import {generateKeyPairSync, createHash, createPublicKey, createPrivateKey} from 'node:crypto'; + +let privateKey, publicKey, fingerprint; + +export async function initJwt() { + const secretPath = process.env.JWT_SECRET_PATH; + if (!secretPath || !existsSync(secretPath)) { + throw new Error('JWT secret path is not defined in environment variables, or the directory does not exist.'); + } + + const privateKeyPath = `${secretPath}/jwt.key`; + const publicKeyPath = `${secretPath}/jwt.key.pub`; + + if (!existsSync(privateKeyPath)) { + console.log("[JWT] Generating new keypair"); + const keyPair = generateKeyPairSync("ec", { + namedCurve: "secp521r1", + }); + + privateKey = keyPair.privateKey; + publicKey = keyPair.publicKey; + + await Promise.all([ + writeFile( + privateKeyPath, + privateKey.export({format: "pem", type: "sec1"}), + ), + writeFile( + publicKeyPath, + publicKey.export({format: "pem", type: "spki"}), + ), + ]); + console.log("[JWT] Keypair generated successfully."); + } else { + console.log("[JWT] Using existing keypair"); + const loadedPrivateKey = await readFile(privateKeyPath, 'utf8'); + const loadedPublicKey = await readFile(publicKeyPath, 'utf8'); + + privateKey = createPrivateKey(loadedPrivateKey); + publicKey = createPublicKey(loadedPublicKey); + } + + fingerprint = createHash("sha256") + .update(publicKey.export({format: "pem", type: "spki"})) + .digest("hex"); +} + +/** + * @type {import('jsonwebtoken').JwtOptions} + */ +const jwtOptions = { + algorithm: 'ES512', +} + +export async function generateJwtToken(user) { + +} + +export async function validateJwtToken(token) { + +} \ No newline at end of file diff --git a/src/util/secretUtils.js b/src/util/secretUtils.js index bbad8ca..92e1b1c 100644 --- a/src/util/secretUtils.js +++ b/src/util/secretUtils.js @@ -1,6 +1,7 @@ import fs from 'node:fs/promises'; -export async function readSecret(path) { +export async function readSecret(name, path) { + console.log(`[SECRET] Reading secret "${name}" from path: ${path}`); if (!path) { throw new Error('Path to secret file is required'); } -- cgit 1.5.1