// Set before requiring auth.js (reads JWT_SECRET at load) and db.js (builds the // pool at load). Pointing the DB at a closed port stops the pool from eagerly // opening idle connections that would keep this test process alive — none of // these tests touch the database. process.env.JWT_SECRET = process.env.JWT_SECRET || 'test-secret' process.env.DB_HOST = '127.0.0.1' process.env.DB_PORT = '59999' const { test, after } = require('node:test') const assert = require('node:assert/strict') const speakeasy = require('speakeasy') const totp = require('../src/utils/totp') const { needsTotp } = require('../src/router/v1/auth/auth.controller') const { signTotpChallenge, verifyTotpChallenge, getUserFromRequest } = require('../src/utils/auth') const db = require('../src/utils/db') after(() => db.close()) test('needsTotp: disabled user does not require a second factor', () => { assert.equal(needsTotp({ id: 1, totp_enabled: 0 }), false) assert.equal(needsTotp({ id: 1 }), false) }) test('needsTotp: enabled user requires a second factor', () => { assert.equal(needsTotp({ id: 1, totp_enabled: 1 }), true) }) test('verifyCode accepts a current code and rejects a wrong/absent one', () => { const { base32 } = totp.generateSecret('alice') const good = speakeasy.totp({ secret: base32, encoding: 'base32' }) assert.equal(totp.verifyCode(base32, good), true) assert.equal(totp.verifyCode(base32, '000000'), false) assert.equal(totp.verifyCode(base32, ''), false) assert.equal(totp.verifyCode(null, good), false) }) test('generateSecret yields a base32 secret and an otpauth URL', () => { const s = totp.generateSecret('bob') assert.ok(s.base32 && s.base32.length >= 16) assert.match(s.otpauthUrl, /^otpauth:\/\/totp\//) }) test('qrDataUrl renders the otpauth URL to a PNG data URL', async () => { const s = totp.generateSecret('carol') const dataUrl = await totp.qrDataUrl(s.otpauthUrl) assert.match(dataUrl, /^data:image\/png;base64,/) }) // The password-verified challenge must never work as a real session token. test('TOTP challenge token is not accepted as a session', () => { const token = signTotpChallenge({ id: 42 }) // Valid as a challenge... const challenge = verifyTotpChallenge(token) assert.equal(challenge.id, 42) // ...but rejected as a session (stage-tagged) when presented as a cookie/bearer. const req = { cookies: {}, headers: { authorization: `Bearer ${token}` } } assert.equal(getUserFromRequest(req), null) }) test('a normal session token is not accepted as a TOTP challenge', () => { const { signToken } = require('../src/utils/auth') const session = signToken({ id: 7, username: 'x', role: 'admin' }) assert.equal(verifyTotpChallenge(session), null) })