Stabilize mobile auth session handling

This commit is contained in:
2026-06-29 17:58:50 -04:00
parent 477459edd4
commit 57e1aa658a
25 changed files with 1126 additions and 192 deletions
+55
View File
@@ -0,0 +1,55 @@
import { getCookie as serializeStoredCookies } from "@better-auth/expo/client";
import * as SecureStore from "expo-secure-store";
import type { createAuthClient } from "better-auth/react";
import { normalizeSecureStoreKey } from "@/lib/secure-store-keys";
type AuthClient = ReturnType<typeof createAuthClient>;
const CHUNK_MARKER = "\u0001ba-chunks:";
function readSecureStoreValueSync(key: string): string | null {
const value = SecureStore.getItem(key);
if (value == null) return null;
if (!value.startsWith(CHUNK_MARKER)) return value;
const count = Number(value.slice(CHUNK_MARKER.length));
if (!Number.isInteger(count) || count < 1) return null;
let assembled = "";
for (let index = 0; index < count; index += 1) {
const chunk = SecureStore.getItem(`${key}.${index}`);
if (chunk == null) return null;
assembled += chunk;
}
return assembled;
}
/** Read session cookie string for tRPC requests (Expo client plugin + SecureStore fallback). */
export function getAuthCookie(
authClient: AuthClient,
storagePrefix: string,
): string | null {
const fromClient = (
authClient as AuthClient & { getCookie?: () => string }
).getCookie?.();
if (fromClient?.trim()) return fromClient.trim();
const raw = readSecureStoreValueSync(
normalizeSecureStoreKey(`${storagePrefix}_cookie`),
);
if (!raw || raw === "{}") return null;
const cookie = serializeStoredCookies(raw);
return cookie.trim() || null;
}
export function getAuthCookieHeaders(
authClient: AuthClient,
storagePrefix: string,
): Record<string, string> {
const cookie = getAuthCookie(authClient, storagePrefix);
return cookie
? { cookie, Cookie: cookie, "x-beenvoice-auth-cookie": cookie }
: {};
}