Add byte-compatible Auth & SSO core primitives
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.
This commit is contained in:
1 parent
5fd40feaa6
commit
ec2d46e583
11 files changed
+511
No files matched your search
@@ -0,0 +1,34 @@
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
import { generateSsoTicket, issueSsoTicket } from "./sso-ticket";
|
||||
|
||||
const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/;
|
||||
|
||||
describe("generateSsoTicket", () => {
|
||||
it("uses '{hotelName-without-spaces}-{uuidv4}'", () => {
|
||||
const t = generateSsoTicket("Atom Hotel");
|
||||
expect(t.startsWith("AtomHotel-")).toBe(true);
|
||||
expect(UUID_RE.test(t.slice("AtomHotel-".length))).toBe(true);
|
||||
});
|
||||
|
||||
it("strips every space in the hotel name", () => {
|
||||
expect(generateSsoTicket("My Cool Hotel").startsWith("MyCoolHotel-")).toBe(true);
|
||||
});
|
||||
|
||||
it("produces a fresh ticket each call", () => {
|
||||
expect(generateSsoTicket("Atom")).not.toBe(generateSsoTicket("Atom"));
|
||||
});
|
||||
});
|
||||
|
||||
describe("issueSsoTicket", () => {
|
||||
it("writes auth_ticket AND ip_current and returns the ticket", async () => {
|
||||
const update = vi.fn().mockResolvedValue(undefined);
|
||||
const db = { user: { update } };
|
||||
const ticket = await issueSsoTicket(db, 42, "Atom Hotel", "1.2.3.4");
|
||||
|
||||
expect(ticket.startsWith("AtomHotel-")).toBe(true);
|
||||
expect(update).toHaveBeenCalledWith({
|
||||
where: { id: 42 },
|
||||
data: { authTicket: ticket, ipCurrent: "1.2.3.4" },
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user