From 3584b3facf7641f18db6eafe7035f17de8c5086c Mon Sep 17 00:00:00 2001 From: Nicolai Ort Date: Fri, 20 Feb 2026 19:10:15 +0100 Subject: [PATCH] feat(auth): Switch scanstation auth from argon2 to sha256 to improve performance --- src/config.ts | 23 +++++++++++-------- src/middlewares/ScanAuth.ts | 9 ++++++-- .../actions/create/CreateScanStation.ts | 4 ++-- 3 files changed, 23 insertions(+), 13 deletions(-) diff --git a/src/config.ts b/src/config.ts index a58f68a..3f4754d 100644 --- a/src/config.ts +++ b/src/config.ts @@ -4,11 +4,12 @@ import { CountryCode } from 'libphonenumber-js'; import ValidatorJS from 'validator'; configDotenv(); -export const config = { - internal_port: parseInt(process.env.APP_PORT) || 4010, - development: process.env.NODE_ENV === "production", - testing: process.env.NODE_ENV === "test", - jwt_secret: process.env.JWT_SECRET || "secretjwtsecret", +export const config = { + internal_port: parseInt(process.env.APP_PORT) || 4010, + development: process.env.NODE_ENV === "production", + testing: process.env.NODE_ENV === "test", + jwt_secret: process.env.JWT_SECRET || "secretjwtsecret", + station_token_secret: process.env.STATION_TOKEN_SECRET || "", phone_validation_countrycode: getPhoneCodeLocale(), postalcode_validation_countrycode: getPostalCodeLocale(), version: process.env.VERSION || require('../package.json').version, @@ -28,10 +29,14 @@ if (typeof config.development !== "boolean") { consola.error("Error: NODE_ENV is not a boolean") errors++ } -if (config.mailer_url == "" || config.mailer_key == "") { - consola.error("Error: invalid mailer config") - errors++; -} +if (config.mailer_url == "" || config.mailer_key == "") { + consola.error("Error: invalid mailer config") + errors++; +} +if (config.station_token_secret.length < 32) { + consola.error("Error: STATION_TOKEN_SECRET must be set and at least 32 characters long") + errors++; +} function getPhoneCodeLocale(): CountryCode { return (process.env.PHONE_COUNTRYCODE as CountryCode); } diff --git a/src/middlewares/ScanAuth.ts b/src/middlewares/ScanAuth.ts index 57f8248..13ef05e 100644 --- a/src/middlewares/ScanAuth.ts +++ b/src/middlewares/ScanAuth.ts @@ -1,6 +1,7 @@ -import { verify } from '@node-rs/argon2'; +import crypto from 'crypto'; import { Request, Response } from 'express'; import { getConnectionManager } from 'typeorm'; +import { config } from '../config'; import { ScanStation } from '../models/entities/ScanStation'; import authchecker from './authchecker'; @@ -57,8 +58,12 @@ const ScanAuth = async (req: Request, res: Response, next: () => void) => { else { if (station.enabled == false) { res.status(401).send({ http_code: 401, short: "station_disabled", message: "Station is disabled." }); + return; } - if (!(await verify(station.key, provided_token))) { + const expectedHash = crypto.createHmac("sha256", config.station_token_secret).update(provided_token).digest('hex'); + const expectedHashBuf = Buffer.from(expectedHash); + const providedHashBuf = Buffer.from(station.key); + if (expectedHashBuf.length !== providedHashBuf.length || !crypto.timingSafeEqual(expectedHashBuf, providedHashBuf)) { res.status(401).send({ http_code: 401, short: "invalid_token", message: "Api token non-existent or invalid syntax." }); return; } diff --git a/src/models/actions/create/CreateScanStation.ts b/src/models/actions/create/CreateScanStation.ts index 241dc76..bda4d80 100644 --- a/src/models/actions/create/CreateScanStation.ts +++ b/src/models/actions/create/CreateScanStation.ts @@ -1,8 +1,8 @@ -import { hash } from '@node-rs/argon2'; import { IsBoolean, IsInt, IsOptional, IsPositive, IsString } from 'class-validator'; import crypto from 'crypto'; import { getConnection } from 'typeorm'; import * as uuid from 'uuid'; +import { config } from '../../../config'; import { TrackNotFoundError } from '../../../errors/TrackErrors'; import { ScanStation } from '../../entities/ScanStation'; import { Track } from '../../entities/Track'; @@ -44,8 +44,8 @@ export class CreateScanStation { let newUUID = uuid.v4().toUpperCase(); newStation.prefix = crypto.createHash("sha3-512").update(newUUID).digest('hex').substring(0, 7).toUpperCase(); - newStation.key = await hash(newStation.prefix + "." + newUUID); newStation.cleartextkey = newStation.prefix + "." + newUUID; + newStation.key = crypto.createHmac("sha256", config.station_token_secret).update(newStation.cleartextkey).digest('hex'); return newStation; }