refactor(cookies): centralize cookie cache version validation (#11254)

Co-authored-by: Taesu <bytaesu@gmail.com>
This commit is contained in:
Emmanuel Lucius
2026-09-11 08:29:35 +00:00
committed by GitHub
co-authored by Taesu
parent 9ca15f3726
commit 34ad3becc2
+36 -62
View File
@@ -1,4 +1,5 @@
import type {
Awaitable,
BetterAuthCookie,
BetterAuthCookies,
BetterAuthOptions,
@@ -591,6 +592,24 @@ export const getSessionCookie = (
return null;
};
type CookieCacheVersion =
| string
| ((
session: CookieCachePayload["session"],
user: CookieCachePayload["user"],
) => Awaitable<string>);
async function matchesVersion(
payload: CookieCachePayload,
version: CookieCacheVersion,
) {
const expectedVersion =
typeof version === "string"
? version
: await version(payload.session, payload.user);
return (payload.version || "1") === expectedVersion;
}
export const getCookieCache = async <
S extends CookieCachePayload = CookieCachePayload,
>(
@@ -609,16 +628,7 @@ export const getCookieCache = async <
audience?: string;
}
| undefined;
version?:
| string
| ((
session: CookieCachePayload["session"],
user: CookieCachePayload["user"],
) => string)
| ((
session: CookieCachePayload["session"],
user: CookieCachePayload["user"],
) => Promise<string>);
version?: CookieCacheVersion;
}
| undefined,
) => {
@@ -682,28 +692,15 @@ export const getCookieCache = async <
"better-auth-session",
);
const payload = parseCookieCachePayload(decoded);
if (!payload) return null;
if (payload) {
// Validate version if provided
if (config?.version) {
const cookieVersion = payload.version || "1";
let expectedVersion = "1";
if (typeof config.version === "string") {
expectedVersion = config.version;
} else if (typeof config.version === "function") {
const result = config.version(payload.session, payload.user);
expectedVersion = isPromise(result) ? await result : result;
}
if (cookieVersion !== expectedVersion) {
return null;
}
}
if (isEmbeddedSessionExpired(payload.session)) {
return null;
}
return payload as S;
if (config?.version) {
const versionMatches = await matchesVersion(payload, config.version);
if (!versionMatches) return null;
}
return null;
if (isEmbeddedSessionExpired(payload.session)) return null;
return payload as S;
} else if (strategy === "jwt") {
const jwks = config?.jwt?.jwks;
let payload: CookieCachePayload | null;
@@ -722,28 +719,15 @@ export const getCookieCache = async <
const decoded = await verifySecretJWT<unknown>(sessionData, secret);
payload = parseCookieCachePayload(decoded);
}
if (!payload) return null;
if (payload) {
// Validate version if provided
if (config?.version) {
const cookieVersion = payload.version || "1";
let expectedVersion = "1";
if (typeof config.version === "string") {
expectedVersion = config.version;
} else if (typeof config.version === "function") {
const result = config.version(payload.session, payload.user);
expectedVersion = isPromise(result) ? await result : result;
}
if (cookieVersion !== expectedVersion) {
return null;
}
}
if (isEmbeddedSessionExpired(payload.session)) {
return null;
}
return payload as S;
if (config?.version) {
const versionMatches = await matchesVersion(payload, config.version);
if (!versionMatches) return null;
}
return null;
if (isEmbeddedSessionExpired(payload.session)) return null;
return payload as S;
} else {
const secret = config?.secret || env.BETTER_AUTH_SECRET;
if (!secret) {
@@ -773,19 +757,9 @@ export const getCookieCache = async <
if (!payload) {
return null;
}
// Validate version if provided
if (config?.version) {
const cookieVersion = payload.version || "1";
let expectedVersion = "1";
if (typeof config.version === "string") {
expectedVersion = config.version;
} else if (typeof config.version === "function") {
const result = config.version(payload.session, payload.user);
expectedVersion = isPromise(result) ? await result : result;
}
if (cookieVersion !== expectedVersion) {
return null;
}
const versionMatches = await matchesVersion(payload, config.version);
if (!versionMatches) return null;
}
// The compact strategy carries no `exp` claim, so the outer cache window