mirror of
https://github.com/better-auth/better-auth.git
synced 2026-06-02 04:16:38 -05:00
fix: prevent stateless refresh with database configured (#6700)
This commit is contained in:
committed by
github-actions[bot]
parent
99defeaf80
commit
9fed2ff3ad
@@ -913,7 +913,7 @@ describe("cookie cache refreshCache", async () => {
|
||||
expect(fn).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it("should refresh cache stateless when refreshCache threshold is exceeded", async () => {
|
||||
it("should not perform stateless refresh when a database is configured", async () => {
|
||||
const callsBefore = fn.mock.calls.length;
|
||||
|
||||
vi.useFakeTimers();
|
||||
@@ -930,9 +930,10 @@ describe("cookie cache refreshCache", async () => {
|
||||
});
|
||||
expect(session.data).not.toBeNull();
|
||||
|
||||
// With stateless refresh, no DB call should be made (it just refreshes the cookie)
|
||||
// With a database configured, `refreshCache` is ignored (a warning is logged),
|
||||
// so no additional DB call should be made here.
|
||||
const callsAfterRefresh = fn.mock.calls.length;
|
||||
expect(callsAfterRefresh).toBe(callsBefore); // No DB call for stateless refresh
|
||||
expect(callsAfterRefresh).toBe(callsBefore);
|
||||
|
||||
await client.getSession({
|
||||
fetchOptions: {
|
||||
@@ -1057,6 +1058,8 @@ describe("cookie cache refreshCache", async () => {
|
||||
|
||||
it("should work without database when refreshCache threshold is reached", async () => {
|
||||
const { client, testUser, cookieSetter, auth } = await getTestInstance({
|
||||
// True stateless mode: no database configured
|
||||
database: undefined as any,
|
||||
session: {
|
||||
cookieCache: {
|
||||
enabled: true,
|
||||
|
||||
@@ -226,9 +226,12 @@ export const getSession = <Option extends BetterAuthOptions>() =>
|
||||
maxAge: 0,
|
||||
});
|
||||
} else {
|
||||
const cachedSessionExpiresAt = new Date(
|
||||
session.session.expiresAt as unknown as string | number | Date,
|
||||
);
|
||||
const hasExpired =
|
||||
sessionDataPayload.expiresAt < Date.now() ||
|
||||
session.session.expiresAt < new Date();
|
||||
cachedSessionExpiresAt < new Date();
|
||||
|
||||
if (hasExpired) {
|
||||
// When the session data cookie has expired, delete it;
|
||||
|
||||
@@ -329,6 +329,58 @@ describe("base context creation", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("should disable cookieRefreshCache and warn when database is configured with refreshCache=true", async () => {
|
||||
const log = vi.fn();
|
||||
const res = await initBase({
|
||||
logger: {
|
||||
level: "warn",
|
||||
log,
|
||||
} as any,
|
||||
database: new Database(":memory:"),
|
||||
session: {
|
||||
cookieCache: {
|
||||
refreshCache: true,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
expect(res.sessionConfig.cookieRefreshCache).toBe(false);
|
||||
expect(log).toHaveBeenCalledWith(
|
||||
"warn",
|
||||
expect.stringContaining(
|
||||
"`session.cookieCache.refreshCache` is enabled while `database` or `secondaryStorage` is configured",
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
it("should disable cookieRefreshCache and warn when secondaryStorage is configured with refreshCache=true", async () => {
|
||||
const log = vi.fn();
|
||||
const res = await initBase({
|
||||
logger: {
|
||||
level: "warn",
|
||||
log,
|
||||
} as any,
|
||||
secondaryStorage: {
|
||||
get: vi.fn(),
|
||||
set: vi.fn(),
|
||||
delete: vi.fn(),
|
||||
},
|
||||
session: {
|
||||
cookieCache: {
|
||||
refreshCache: true,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
expect(res.sessionConfig.cookieRefreshCache).toBe(false);
|
||||
expect(log).toHaveBeenCalledWith(
|
||||
"warn",
|
||||
expect.stringContaining(
|
||||
"`session.cookieCache.refreshCache` is enabled while `database` or `secondaryStorage` is configured",
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
it("should use default maxAge (300) for 20% calculation", async () => {
|
||||
const res = await initBase({
|
||||
session: {
|
||||
|
||||
@@ -197,6 +197,17 @@ export async function createAuthContext(
|
||||
const refreshCache = options.session?.cookieCache?.refreshCache;
|
||||
const maxAge = options.session?.cookieCache?.maxAge || 60 * 5;
|
||||
|
||||
// `refreshCache` is intended for fully stateless / DB-less setups.
|
||||
// If a server-side store is configured, prefer fetching/refreshing from that source
|
||||
// and disable stateless refresh behavior to avoid confusing/unsafe configurations.
|
||||
const isStateful = !!options.database || !!options.secondaryStorage;
|
||||
if (isStateful && refreshCache) {
|
||||
logger.warn(
|
||||
"[better-auth] `session.cookieCache.refreshCache` is enabled while `database` or `secondaryStorage` is configured. `refreshCache` is meant for stateless (DB-less) setups. Disabling `refreshCache` — remove it from your config to silence this warning.",
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (refreshCache === false || refreshCache === undefined) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user