fix: use deterministic HKDF key for cookie signing

cookieMac was using encryptString which generates a random IV per
call, making the HMAC key non-deterministic. Cookie signed at login
could never verify on subsequent requests. Now uses deriveKey(info)
which uses HKDF — deterministic for same server key.
This commit is contained in:
Mitchell R 2026-05-10 02:59:04 +02:00
parent fe11519925
commit bacf1d2fcb
No known key found for this signature in database
2 changed files with 8 additions and 2 deletions

View file

@ -170,9 +170,10 @@ export function createAuth(
// ---- Sessions ------------------------------------------------------------- // ---- Sessions -------------------------------------------------------------
const cookieKey = secrets.deriveKey("cookie");
function cookieMac(sid: string): string { function cookieMac(sid: string): string {
const subkeyMaterial = secrets.encryptString("cookie-subkey", "cookie-derivation"); return createHmac("sha256", cookieKey).update(sid).digest("hex");
return createHmac("sha256", subkeyMaterial).update(sid).digest("hex");
} }
function signCookie(sid: string): string { function signCookie(sid: string): string {

View file

@ -33,6 +33,7 @@ export interface SecretsLog {
export interface SecretsApi { export interface SecretsApi {
encryptString(plaintext: string, info?: string): string; encryptString(plaintext: string, info?: string): string;
decryptString(ciphertext: string, info?: string): string; decryptString(ciphertext: string, info?: string): string;
deriveKey(info: string): Buffer;
generateClusterKey(): string; generateClusterKey(): string;
encryptForCluster(plaintext: string, clusterKeyB64u: string): string; encryptForCluster(plaintext: string, clusterKeyB64u: string): string;
} }
@ -54,6 +55,10 @@ export function initSecrets(config: SecretsConfig, log: SecretsLog): SecretsApi
} }
return { return {
deriveKey(info: string): Buffer {
return deriveSubkey(info);
},
encryptString(plaintext: string, info: string = "field"): string { encryptString(plaintext: string, info: string = "field"): string {
const subkey = deriveSubkey(info); const subkey = deriveSubkey(info);
const iv = randomBytes(12); const iv = randomBytes(12);