mirror of
https://github.com/better-auth/better-auth.git
synced 2026-10-19 23:53:17 -05:00
fix(expo): prevent null cookie key when redirect URL has no cookie param (#7555)
This commit is contained in:
@@ -396,7 +396,7 @@ export const expoClient = (opts: ExpoClientOptions) => {
|
||||
// Only process and notify if the Set-Cookie header contains better-auth cookies
|
||||
// This prevents infinite refetching when other cookies (like Cloudflare's __cf_bm) are present
|
||||
if (hasBetterAuthCookies(setCookie, cookiePrefix)) {
|
||||
const prevCookie = await storage.getItem(cookieName);
|
||||
const prevCookie = storage.getItem(cookieName);
|
||||
const toSetCookie = getSetCookie(
|
||||
setCookie || "",
|
||||
prevCookie ?? undefined,
|
||||
@@ -408,7 +408,7 @@ export const expoClient = (opts: ExpoClientOptions) => {
|
||||
store?.notify("$sessionSignal");
|
||||
} else {
|
||||
// Still update the storage to refresh expiry times, but don't trigger refetch
|
||||
await storage.setItem(cookieName, toSetCookie);
|
||||
storage.setItem(cookieName, toSetCookie);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -449,7 +449,7 @@ export const expoClient = (opts: ExpoClientOptions) => {
|
||||
} catch {}
|
||||
}
|
||||
|
||||
const storedCookieJson = await storage.getItem(cookieName);
|
||||
const storedCookieJson = storage.getItem(cookieName);
|
||||
const oauthStateValue = getOAuthStateValue(
|
||||
storedCookieJson,
|
||||
cookiePrefix,
|
||||
@@ -468,9 +468,9 @@ export const expoClient = (opts: ExpoClientOptions) => {
|
||||
);
|
||||
if (result.type !== "success") return;
|
||||
const url = new URL(result.url);
|
||||
const cookie = String(url.searchParams.get("cookie"));
|
||||
const cookie = url.searchParams.get("cookie");
|
||||
if (!cookie) return;
|
||||
const prevCookie = await storage.getItem(cookieName);
|
||||
const prevCookie = storage.getItem(cookieName);
|
||||
const toSetCookie = getSetCookie(cookie, prevCookie ?? undefined);
|
||||
storage.setItem(cookieName, toSetCookie);
|
||||
store?.notify("$sessionSignal");
|
||||
@@ -519,7 +519,7 @@ export const expoClient = (opts: ExpoClientOptions) => {
|
||||
}
|
||||
}
|
||||
if (url.includes("/sign-out")) {
|
||||
await storage.setItem(cookieName, "{}");
|
||||
storage.setItem(cookieName, "{}");
|
||||
store?.atoms.session?.set({
|
||||
...store.atoms.session.get(),
|
||||
data: null,
|
||||
|
||||
@@ -427,6 +427,44 @@ describe("expo", async () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("should not corrupt cookies when redirect URL has no cookie param", async () => {
|
||||
await client.signIn.email({
|
||||
email: testUser.email,
|
||||
password: testUser.password,
|
||||
});
|
||||
|
||||
const storedCookieBefore = storage.get("better-auth_cookie");
|
||||
expect(storedCookieBefore).toBeDefined();
|
||||
const parsedCookieBefore = JSON.parse(storedCookieBefore || "");
|
||||
expect(parsedCookieBefore["better-auth.session_token"]).toBeDefined();
|
||||
|
||||
const expoWebBrowser = await import("expo-web-browser");
|
||||
|
||||
vi.mocked(expoWebBrowser.openAuthSessionAsync).mockResolvedValueOnce({
|
||||
type: "success",
|
||||
url: "better-auth:///dashboard", // No cookie param
|
||||
});
|
||||
|
||||
await client.signIn.social({
|
||||
provider: "google",
|
||||
callbackURL: "/dashboard",
|
||||
});
|
||||
|
||||
// Cookies should be preserved, not corrupted with "null" key
|
||||
const storedCookieAfter = storage.get("better-auth_cookie");
|
||||
expect(storedCookieAfter).toBeDefined();
|
||||
const parsedCookieAfter = JSON.parse(storedCookieAfter || "");
|
||||
|
||||
// Should NOT have "null" as a cookie key
|
||||
expect(parsedCookieAfter["null"]).toBeUndefined();
|
||||
|
||||
// Original session_token should still exist
|
||||
expect(parsedCookieAfter["better-auth.session_token"]).toBeDefined();
|
||||
expect(parsedCookieAfter["better-auth.session_token"]?.value).toBe(
|
||||
parsedCookieBefore["better-auth.session_token"]?.value,
|
||||
);
|
||||
});
|
||||
|
||||
it("should NOT include oauthState param in proxy URL when using database strategy", async () => {
|
||||
fn.mockClear();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user