71 lines
1.9 KiB
TypeScript
71 lines
1.9 KiB
TypeScript
import { describe, expect, it } from 'vitest';
|
|
import crypto from 'node:crypto';
|
|
import {
|
|
hashPasswordArgon2id,
|
|
randomToken,
|
|
sha256Token,
|
|
signAccessToken,
|
|
verifyAccessToken,
|
|
verifyPasswordArgon2id
|
|
} from './index.js';
|
|
|
|
describe('auth primitives', () => {
|
|
it('hashes and verifies Argon2id passwords with PHC metadata', async () => {
|
|
const secret = crypto.randomUUID();
|
|
const hash = await hashPasswordArgon2id(secret, {
|
|
salt: Buffer.alloc(16, 7),
|
|
memoryKiB: 1024,
|
|
passes: 1
|
|
});
|
|
|
|
expect(hash).toMatch(/^\$argon2id\$v=19\$m=1024,t=1,p=1\$/);
|
|
await expect(verifyPasswordArgon2id(secret, hash)).resolves.toBe(true);
|
|
await expect(verifyPasswordArgon2id(crypto.randomUUID(), hash)).resolves.toBe(false);
|
|
});
|
|
|
|
it('hashes refresh tokens without retaining token material', () => {
|
|
const token = randomToken();
|
|
const digest = sha256Token(token);
|
|
|
|
expect(token).not.toContain(digest);
|
|
expect(digest).toMatch(/^[a-f0-9]{64}$/);
|
|
});
|
|
|
|
it('signs and verifies expiring access tokens', () => {
|
|
const secret = 'test-only-access-token-secret-min-32-bytes';
|
|
const token = signAccessToken(
|
|
{
|
|
sub: 'usr_test',
|
|
username: 'operator',
|
|
roles: ['admin'],
|
|
typ: 'access'
|
|
},
|
|
{
|
|
secret,
|
|
issuer: 'lisglosips-api',
|
|
audience: 'lisglosips-web',
|
|
ttlSeconds: 60,
|
|
now: new Date('2026-06-21T00:00:00.000Z')
|
|
}
|
|
);
|
|
|
|
expect(
|
|
verifyAccessToken(token, {
|
|
secret,
|
|
issuer: 'lisglosips-api',
|
|
audience: 'lisglosips-web',
|
|
now: new Date('2026-06-21T00:00:30.000Z')
|
|
})?.sub
|
|
).toBe('usr_test');
|
|
|
|
expect(
|
|
verifyAccessToken(token, {
|
|
secret,
|
|
issuer: 'lisglosips-api',
|
|
audience: 'lisglosips-web',
|
|
now: new Date('2026-06-21T00:02:00.000Z')
|
|
})
|
|
).toBeNull();
|
|
});
|
|
});
|