Pure, unit-tested primitives the AtomCMS->Next.js login must reproduce exactly
(verified now with round-trip + known vectors; full end-to-end check deferred
until a real DB + APP_KEY + live emulator are available):
- password.ts: argon2id (m=65536,t=4,p=1 via hash-wasm) + bcrypt ($2y$ accepted)
verify, and the md5->argon2id on-login upgrade gated by convert_passwords
(mirrors RedirectIfTwoFactorAuthenticatable).
- sso-ticket.ts: '{hotel_name without spaces}-{uuidv4}' written to auth_ticket +
ip_current (mirrors User::ssoTicket()).
- laravel-encrypter.ts: AES-256-CBC + HMAC-SHA256 payload compatible with
Laravel encrypt()/encryptString (for existing 2FA secrets) incl. PHP string
(de)serialization.
- totp.ts: otplib Google2FA-compatible TOTP verify (SHA1/6/30).
Libs: hash-wasm + bcryptjs + otplib (pure JS/WASM, no native build). 28 tests.
28 lines
878 B
TypeScript
28 lines
878 B
TypeScript
import { describe, expect, it } from "vitest";
|
|
import { generateTotp, totpKeyUri, verifyTotp } from "./totp";
|
|
|
|
const SECRET = "JBSWY3DPEHPK3PXP"; // standard base32 test secret
|
|
|
|
describe("totp", () => {
|
|
it("verifies the current generated code", () => {
|
|
const code = generateTotp(SECRET);
|
|
expect(code).toMatch(/^\d{6}$/);
|
|
expect(verifyTotp(code, SECRET)).toBe(true);
|
|
});
|
|
|
|
it("rejects a wrong code", () => {
|
|
expect(verifyTotp("000000", SECRET)).toBe(false);
|
|
});
|
|
|
|
it("rejects malformed input without throwing", () => {
|
|
expect(verifyTotp("not-a-code", SECRET)).toBe(false);
|
|
});
|
|
|
|
it("builds an otpauth provisioning URI", () => {
|
|
const uri = totpKeyUri(SECRET, "alice", "AtomHotel");
|
|
expect(uri.startsWith("otpauth://totp/")).toBe(true);
|
|
expect(uri).toContain("secret=" + SECRET);
|
|
expect(uri).toContain("issuer=AtomHotel");
|
|
});
|
|
});
|