add rotating keys
This commit is contained in:
parent
f0ab000415
commit
d92305e504
@ -10,6 +10,8 @@
|
||||
"typescript": "^5.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"express-fingerprint": "^1.2.2"
|
||||
"crypto": "^1.0.1",
|
||||
"express-fingerprint": "^1.2.2",
|
||||
"node-fetch": "^3.3.2"
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,8 +1,11 @@
|
||||
import { Request, RequestHandler } from "express";
|
||||
import { getRedisClient } from "../clients/db/RedisDbProvider";
|
||||
import { getAuthModes, getDoorSettingString } from "../util/EnvConfigUtil";
|
||||
import { getAllDoorNames, getAuthModes, getDoorSettingString } from "../util/EnvConfigUtil";
|
||||
import { IAuthMode } from "../types/IAuthMode";
|
||||
import { IDoorConfig } from "../types/IDoorConfig";
|
||||
import { doorRotatingKey } from "../types/RedisKeys";
|
||||
import crypto from "crypto";
|
||||
import fetch from "node-fetch";
|
||||
|
||||
const client = await getRedisClient();
|
||||
|
||||
@ -14,12 +17,15 @@ export const HandleAuthMode: RequestHandler = async (req, res, next) => {
|
||||
return;
|
||||
}
|
||||
|
||||
const isAuthorized = authModes.some((mode) => {
|
||||
const checkAuth = async (mode: IAuthMode): Promise<boolean> => {
|
||||
switch(mode) {
|
||||
case IAuthMode.FIXED_PIN: return handleFixedPinAuth(req)
|
||||
case IAuthMode.RANDOM_ROTATING_KEY: return await handleRandomRotatingKeyAuth(req)
|
||||
default: return false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
const isAuthorized = (await Promise.all(authModes.map((mode) => checkAuth(mode)))).some(b => b);
|
||||
|
||||
if (!isAuthorized) {
|
||||
res.status(401).json({ msg: 'Unauthorized' });
|
||||
@ -32,4 +38,28 @@ export const HandleAuthMode: RequestHandler = async (req, res, next) => {
|
||||
const handleFixedPinAuth = (req: Request): boolean => {
|
||||
const fixedPin = getDoorSettingString(req.params.id, IDoorConfig.FIXED_PIN);
|
||||
return fixedPin !== undefined && req.query['key'] === fixedPin;
|
||||
}
|
||||
|
||||
const handleRandomRotatingKeyAuth = async (req: Request): Promise<boolean> => {
|
||||
const currentPin = await client.get(doorRotatingKey(req.params.id));
|
||||
|
||||
if (currentPin === req.query['rotatingKey']) {
|
||||
await replaceDoorRandomKey(req.params.id);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
export const initializeRandomDoorPins = () => {
|
||||
const doors = getAllDoorNames();
|
||||
doors.forEach(replaceDoorRandomKey);
|
||||
}
|
||||
|
||||
export const replaceDoorRandomKey = async (door: string) => {
|
||||
const newKey = crypto.randomBytes(20).toString('hex');
|
||||
|
||||
await client.put(doorRotatingKey(door), newKey);
|
||||
|
||||
const message = `New key for door ${door}! Unlock link: ${Bun.env.BASE_DOMAIN}/api/door/${door}/auth?rotatingKey=${newKey}`;
|
||||
await fetch(Bun.env.ROTATING_KEY_NTFY, { method: "POST", body: message });
|
||||
}
|
||||
@ -1,7 +1,11 @@
|
||||
import express from "express";
|
||||
import DoorRouter from "./routers/DoorRouter";
|
||||
import { getAllDoorNames } from "./util/EnvConfigUtil";
|
||||
import { getRedisClient } from "./clients/db/RedisDbProvider";
|
||||
import { initializeRandomDoorPins } from "./middlewares/DoorAuthModes";
|
||||
|
||||
const Fingerprint = require('express-fingerprint');
|
||||
const client = getRedisClient();
|
||||
|
||||
const app = express();
|
||||
|
||||
@ -25,4 +29,5 @@ app.use('/api/door', DoorRouter);
|
||||
|
||||
app.listen(5000, async () => {
|
||||
console.log("listening on port 5000");
|
||||
initializeRandomDoorPins();
|
||||
});
|
||||
@ -5,5 +5,6 @@ declare module "bun" {
|
||||
REDIS_CONNECT_URL: string; // `redis[s]://[[username][:password]@][host][:port][/db-number]`
|
||||
DOOR_OPEN_TIMEOUT: number;
|
||||
DOOR_FIXED_PIN: string;
|
||||
ROTATING_KEY_NTFY: string;
|
||||
}
|
||||
}
|
||||
@ -1,3 +1,4 @@
|
||||
export enum IAuthMode {
|
||||
FIXED_PIN = "FIXED_PIN",
|
||||
RANDOM_ROTATING_KEY = "RANDOM_ROTATING_KEY",
|
||||
}
|
||||
@ -7,6 +7,10 @@ export function doorStatusKey(id: string) {
|
||||
return concatKeys(RedisKeys.DOORS, id, 'open');
|
||||
}
|
||||
|
||||
export function doorRotatingKey(id: string) {
|
||||
return concatKeys(RedisKeys.DOORS, id, 'rotatingKey');
|
||||
}
|
||||
|
||||
export function concatKeys(...keys: String[]) {
|
||||
return keys.join(':');
|
||||
}
|
||||
@ -36,4 +36,16 @@ export const getDoorSettingTimeLock = (door: string): number[] => {
|
||||
|
||||
// never locked (always -1 < hr < 25)
|
||||
return [25, -1];
|
||||
}
|
||||
|
||||
export const getAllDoorNames = (): string[] => {
|
||||
const names: string[] = [];
|
||||
|
||||
Object.keys(Bun.env).forEach(key => {
|
||||
if (key.startsWith(IDoorConfig.AUTH_MODES)) {
|
||||
names.push(key.replace(IDoorConfig.AUTH_MODES + "_", "").toLowerCase());
|
||||
}
|
||||
});
|
||||
|
||||
return names;
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user