diff --git a/packages/expo/src/client.ts b/packages/expo/src/client.ts index cf9edaa5ae..0f957eb1e1 100644 --- a/packages/expo/src/client.ts +++ b/packages/expo/src/client.ts @@ -238,12 +238,39 @@ export function hasBetterAuthCookies( return false; } +/** + * Expo secure store does not support colons in the keys. + * This function replaces colons with underscores. + * + * @see https://github.com/better-auth/better-auth/issues/5426 + * + * @param name cookie name to be saved in the storage + * @returns normalized cookie name + */ +export function normalizeCookieName(name: string) { + return name.replace(/:/g, "_"); +} + +export function storageAdapter(storage: { + getItem: (name: string) => string | null; + setItem: (name: string, value: string) => void; +}) { + return { + getItem: (name: string) => { + return storage.getItem(normalizeCookieName(name)); + }, + setItem: (name: string, value: string) => { + return storage.setItem(normalizeCookieName(name), value); + }, + }; +} + export const expoClient = (opts: ExpoClientOptions) => { let store: Store | null = null; const storagePrefix = opts?.storagePrefix || "better-auth"; const cookieName = `${storagePrefix}_cookie`; const localCacheName = `${storagePrefix}_session_data`; - const storage = opts?.storage; + const storage = storageAdapter(opts?.storage); const isWeb = Platform.OS === "web"; const cookiePrefix = opts?.cookiePrefix || "better-auth"; diff --git a/packages/expo/src/expo.test.ts b/packages/expo/src/expo.test.ts index dee41204ac..48459fe746 100644 --- a/packages/expo/src/expo.test.ts +++ b/packages/expo/src/expo.test.ts @@ -2,7 +2,7 @@ import { createAuthClient } from "better-auth/react"; import Database from "better-sqlite3"; import { beforeAll, afterAll, describe, expect, it, vi } from "vitest"; import { expo } from "."; -import { expoClient } from "./client"; +import { expoClient, storageAdapter } from "./client"; import { betterAuth } from "better-auth"; import { getMigrations } from "better-auth/db"; import { oAuthProxy } from "better-auth/plugins"; @@ -325,4 +325,19 @@ describe("expo with cookieCache", async () => { expect(hasBetterAuthCookies(customCookieHeader, "better-auth")).toBe(false); }); + + it("should normalize colons in secure storage name via storage adapter", async () => { + const map = new Map(); + const storage = storageAdapter({ + getItem(name) { + return map.get(name) || null; + }, + setItem(name, value) { + map.set(name, value); + }, + }); + storage.setItem("better-auth:session_token", "123"); + expect(map.has("better-auth_session_token")).toBe(true); + expect(map.has("better-auth:session_token")).toBe(false); + }); });