feat(auth): Switch scanstation auth from argon2 to sha256 to improve performance

This commit is contained in:
2026-02-20 19:10:15 +01:00
parent e27e819609
commit 3584b3facf
3 changed files with 23 additions and 13 deletions

View File

@@ -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);
}

View File

@@ -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;
}

View File

@@ -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;
}