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:
Simo committed 2026-06-27 16:00:25 +02:00
1 parent 5fd40feaa6
commit ec2d46e583
11 files changed
+511

No files matched your search

+24
View File
@@ -0,0 +1,24 @@
import { authenticator } from "otplib";
// Laravel Fortify uses pragmarx/google2fa: HMAC-SHA1, 6 digits, 30s period.
// otplib already defaults to SHA1/6/30; window=1 tolerates one step of skew.
authenticator.options = { window: 1 };
/** Verify a 6-digit TOTP code against a base32 secret. */
export function verifyTotp(token: string, secret: string): boolean {
try {
return authenticator.check(token, secret);
} catch {
return false;
}
}
/** Current TOTP code for a secret (used in tests / tooling). */
export function generateTotp(secret: string): string {
return authenticator.generate(secret);
}
/** otpauth:// URI for provisioning a QR code. */
export function totpKeyUri(secret: string, accountName: string, issuer: string): string {
return authenticator.keyuri(accountName, issuer, secret);
}