Files
chlova/orchestrator/test/auth.test.ts
T
Kantin-Petit e322ed1167 feat: auth surface exposée + ChatService partagé (v0.19.0)
Auth login fort : mot de passe scrypt + TOTP 2FA (otplib) + JWT HS256
(jose), login tout-ou-rien sans indice. ChatService factorise le tour
d'agent pour toutes les surfaces (Telegram refactoré). 60 tests, 0 vuln.

Palier de risque : reversible (logique d'auth ; surface API câblée en v0.20).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-23 02:06:32 +02:00

74 lines
2.2 KiB
TypeScript

import { describe, it, expect } from "vitest";
import { generateSecret, generateSync } from "otplib";
import {
hashPassword,
verifyPassword,
verifyTotp,
issueJwt,
verifyJwt,
login,
type AuthConfig,
} from "../src/api/auth.js";
describe("password (scrypt)", () => {
it("vérifie un mot de passe correct et rejette un faux", () => {
const h = hashPassword("s3cr3t!");
expect(verifyPassword("s3cr3t!", h)).toBe(true);
expect(verifyPassword("wrong", h)).toBe(false);
});
it("rejette un hash malformé", () => {
expect(verifyPassword("x", "pasunhash")).toBe(false);
});
});
describe("TOTP", () => {
it("valide un code généré pour le secret", () => {
const secret = generateSecret();
const code = generateSync({ secret: secret });
expect(verifyTotp(code, secret)).toBe(true);
expect(verifyTotp("000000", secret)).toBe(false);
});
});
const cfg = (): AuthConfig => ({
adminUser: "kantin",
adminPasswordHash: hashPassword("pw"),
totpSecret: generateSecret(),
jwtSecret: "a-very-long-jwt-secret-value-32+chars",
});
describe("JWT", () => {
it("émet et vérifie un JWT", async () => {
const c = cfg();
const token = await issueJwt(c);
expect(await verifyJwt(token, c.jwtSecret)).toBe("kantin");
});
it("rejette un JWT avec mauvais secret", async () => {
const c = cfg();
const token = await issueJwt(c);
expect(await verifyJwt(token, "autre-secret-completement-different")).toBeNull();
});
});
describe("login (mdp + TOTP, tout-ou-rien)", () => {
it("réussit avec les bons facteurs", async () => {
const c = cfg();
const token = await login(c, {
user: "kantin",
password: "pw",
totp: generateSync({ secret: c.totpSecret }),
});
expect(token).not.toBeNull();
});
it("échoue si un seul facteur est faux", async () => {
const c = cfg();
const good = generateSync({ secret: c.totpSecret });
expect(await login(c, { user: "kantin", password: "bad", totp: good })).toBeNull();
expect(await login(c, { user: "kantin", password: "pw", totp: "000000" })).toBeNull();
expect(await login(c, { user: "intrus", password: "pw", totp: good })).toBeNull();
});
});