Skip to content

Commit 98fcb71

Browse files
committed
fix(desktop): persist auth cookies with max age
1 parent 425e861 commit 98fcb71

2 files changed

Lines changed: 66 additions & 2 deletions

File tree

apps/desktop/layer/main/src/lib/auth-cookies.test.ts

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import type { Session } from "electron"
2-
import { describe, expect, it, vi } from "vitest"
2+
import { beforeEach, describe, expect, it, vi } from "vitest"
33

44
import {
55
buildManagedAuthCookieHeader,
@@ -10,6 +10,10 @@ import {
1010
} from "./auth-cookies"
1111

1212
describe("auth cookies", () => {
13+
beforeEach(() => {
14+
vi.useRealTimers()
15+
})
16+
1317
it("builds a cookie header from managed auth cookies only", () => {
1418
const header = buildManagedAuthCookieHeader([
1519
{ name: "__Secure-better-auth.session_token", value: "session-token" },
@@ -104,6 +108,53 @@ describe("auth cookies", () => {
104108
expect(remove).not.toHaveBeenCalled()
105109
})
106110

111+
it("persists session token cookies across app restarts when the server sends Max-Age", async () => {
112+
vi.useFakeTimers()
113+
vi.setSystemTime(new Date("2026-05-12T00:00:00.000Z"))
114+
115+
const set = vi.fn().mockImplementation(async () => {})
116+
const remove = vi.fn().mockImplementation(async () => {})
117+
const get = vi.fn().mockResolvedValue([])
118+
119+
await persistManagedAuthCookiesFromSetCookieHeader({
120+
apiURL: "https://api.folo.is",
121+
session: {
122+
cookies: { get, set, remove },
123+
} as unknown as Session,
124+
setCookieHeader:
125+
"__Secure-better-auth.session_token=session-token; Max-Age=2592000; Path=/; HttpOnly; Secure; SameSite=None",
126+
})
127+
128+
expect(set).toHaveBeenCalledWith(
129+
expect.objectContaining({
130+
name: "__Secure-better-auth.session_token",
131+
value: "session-token",
132+
expirationDate: 1_781_136_000,
133+
}),
134+
)
135+
})
136+
137+
it("keeps rememberMe=false session token cookies session-scoped", async () => {
138+
const set = vi.fn().mockImplementation(async () => {})
139+
const remove = vi.fn().mockImplementation(async () => {})
140+
const get = vi.fn().mockResolvedValue([])
141+
142+
await persistManagedAuthCookiesFromSetCookieHeader({
143+
apiURL: "https://api.folo.is",
144+
session: {
145+
cookies: { get, set, remove },
146+
} as unknown as Session,
147+
setCookieHeader:
148+
"__Secure-better-auth.session_token=session-token; Path=/; HttpOnly; Secure; SameSite=None",
149+
})
150+
151+
expect(set).toHaveBeenCalledWith(
152+
expect.not.objectContaining({
153+
expirationDate: expect.any(Number),
154+
}),
155+
)
156+
})
157+
107158
it("removes stale duplicate session token cookies while keeping the secure host-only cookie", async () => {
108159
const remove = vi.fn().mockImplementation(async () => {})
109160
const get = vi.fn().mockResolvedValue([

apps/desktop/layer/main/src/lib/auth-cookies.ts

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,18 @@ const shouldRemoveCookie = (cookie: ParsedSetCookie) => {
224224
return false
225225
}
226226

227+
const getCookieExpirationDate = (cookie: ParsedSetCookie) => {
228+
if (cookie.expirationDate !== undefined) {
229+
return cookie.expirationDate
230+
}
231+
232+
if (cookie.maxAge !== undefined && cookie.maxAge > 0) {
233+
return Math.floor(Date.now() / 1000) + cookie.maxAge
234+
}
235+
236+
return
237+
}
238+
227239
export const getManagedAuthCookieNames = () => {
228240
return [...MANAGED_AUTH_COOKIE_NAMES]
229241
}
@@ -368,6 +380,7 @@ export const persistManagedAuthCookiesFromSetCookieHeader = async ({
368380
continue
369381
}
370382

383+
const expirationDate = getCookieExpirationDate(cookie)
371384
const details: CookiesSetDetails = {
372385
url: apiURL,
373386
name: cookie.name,
@@ -377,7 +390,7 @@ export const persistManagedAuthCookiesFromSetCookieHeader = async ({
377390
secure: cookie.secure,
378391
...(cookie.sameSite ? { sameSite: cookie.sameSite } : {}),
379392
...(cookie.domain ? { domain: cookie.domain } : {}),
380-
...(cookie.expirationDate ? { expirationDate: cookie.expirationDate } : {}),
393+
...(expirationDate ? { expirationDate } : {}),
381394
}
382395

383396
await session.cookies.set(details)

0 commit comments

Comments
 (0)