src/auth/auth.test.ts
v0.1.0 · 2 KB
import { createHmac } from 'node:crypto';
import { describe, expect, it } from 'vitest';
import { FIXTURE_ACCOUNT, FIXTURE_KEYS } from '../testing/fixtures.js';
import { buildRestAuthHeaders, createNonceSource, createOrderTag, hmacSignature, maskSecrets } from './index.js';
describe('authentication and caller-owned tags', () => {
it('signs nonce and seconds, refusing millisecond timestamps', () => {
const nonce = '12'.repeat(16),
seconds = 1_820_000_000;
expect(hmacSignature(FIXTURE_KEYS.secret, nonce, seconds)).toBe(
createHmac('sha256', FIXTURE_KEYS.secret)
.update(nonce + ':' + seconds)
.digest('hex'),
);
expect(() => hmacSignature(FIXTURE_KEYS.secret, nonce, seconds * 1000)).toThrow();
expect(
buildRestAuthHeaders(FIXTURE_KEYS, FIXTURE_ACCOUNT, seconds * 1000, nonce)['x-qfex-requested-account-id'],
).toBe(FIXTURE_ACCOUNT);
});
it('retries collisions and refuses broken entropy without evicting live nonces', () => {
let index = 0;
const source = createNonceSource({ randomBytes: () => Buffer.alloc(16, index++ < 2 ? 7 : 8) });
const first = source.next(0);
expect(source.next(1)).not.toBe(first);
const broken = createNonceSource({ randomBytes: () => Buffer.alloc(16, 9) });
broken.next(0);
expect(() => broken.next(1)).toThrow();
});
it('requires a caller magic, preserves flags, and rejects case-changed echoes', () => {
expect(() => createOrderTag({ magic: '' })).toThrow();
const tag = createOrderTag({ magic: 'abababab' });
const cloid = tag.next(73);
expect(cloid).toHaveLength(32);
expect(tag.decode(cloid)?.flag).toBe(73);
expect(tag.decode(cloid.toUpperCase())).toBeNull();
expect(tag.decode(createOrderTag({ magic: 'cdcdcdcd' }).next(73))).toBeNull();
});
it('masks explicit secrets and protocol signature-like tokens', () => {
expect(
maskSecrets('fixture-secret api_key=example signature: ' + 'a'.repeat(64), { secret: FIXTURE_KEYS.secret }),
).not.toContain(FIXTURE_KEYS.secret);
});
});