fix: use cookie-based storage for Supabase client auth
Store auth session in cookies instead of localStorage so server-side code (admin layout, API routes, protected layout) can read the session. Implements chunked cookie support for large session tokens. https://claude.ai/code/session_01H2aRGDaKgarPvhay2HxN6Y
This commit is contained in:
@@ -1,9 +1,74 @@
|
|||||||
import { createClient as createSupabaseClient } from "@supabase/supabase-js";
|
import { createClient as createSupabaseClient } from "@supabase/supabase-js";
|
||||||
import type { Database } from "@/types/database.types";
|
import type { Database } from "@/types/database.types";
|
||||||
|
|
||||||
// Client Supabase côté navigateur (composants client)
|
// Storage basé sur les cookies pour que le serveur puisse lire la session
|
||||||
|
// Remplace le localStorage par défaut de Supabase
|
||||||
|
const cookieStorage = {
|
||||||
|
getItem: (key: string): string | null => {
|
||||||
|
if (typeof document === "undefined") return null;
|
||||||
|
|
||||||
|
// Essayer le cookie direct
|
||||||
|
const escaped = key.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
||||||
|
const match = document.cookie.match(
|
||||||
|
new RegExp(`(?:^|; )${escaped}=([^;]*)`)
|
||||||
|
);
|
||||||
|
if (match) return decodeURIComponent(match[1]);
|
||||||
|
|
||||||
|
// Essayer les cookies chunked (.0, .1, .2, ...)
|
||||||
|
const chunks: string[] = [];
|
||||||
|
for (let i = 0; i < 10; i++) {
|
||||||
|
const chunkMatch = document.cookie.match(
|
||||||
|
new RegExp(`(?:^|; )${escaped}\\.${i}=([^;]*)`)
|
||||||
|
);
|
||||||
|
if (chunkMatch) {
|
||||||
|
chunks.push(decodeURIComponent(chunkMatch[1]));
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (chunks.length > 0) return chunks.join("");
|
||||||
|
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
|
||||||
|
setItem: (key: string, value: string): void => {
|
||||||
|
if (typeof document === "undefined") return;
|
||||||
|
|
||||||
|
// Supprimer les anciens cookies d'abord
|
||||||
|
cookieStorage.removeItem(key);
|
||||||
|
|
||||||
|
const maxChunkSize = 3500; // Limite cookie ~4KB avec overhead
|
||||||
|
|
||||||
|
if (value.length <= maxChunkSize) {
|
||||||
|
document.cookie = `${key}=${encodeURIComponent(value)}; path=/; max-age=${60 * 60 * 24 * 365}; SameSite=Lax`;
|
||||||
|
} else {
|
||||||
|
// Découper en chunks
|
||||||
|
for (let i = 0; i * maxChunkSize < value.length; i++) {
|
||||||
|
const chunk = value.substring(i * maxChunkSize, (i + 1) * maxChunkSize);
|
||||||
|
document.cookie = `${key}.${i}=${encodeURIComponent(chunk)}; path=/; max-age=${60 * 60 * 24 * 365}; SameSite=Lax`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
removeItem: (key: string): void => {
|
||||||
|
if (typeof document === "undefined") return;
|
||||||
|
document.cookie = `${key}=; path=/; max-age=0`;
|
||||||
|
for (let i = 0; i < 10; i++) {
|
||||||
|
document.cookie = `${key}.${i}=; path=/; max-age=0`;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
// Client Supabase côté navigateur
|
||||||
|
// Utilise les cookies comme storage pour que le serveur puisse lire la session
|
||||||
export const createClient = () =>
|
export const createClient = () =>
|
||||||
createSupabaseClient<Database>(
|
createSupabaseClient<Database>(
|
||||||
process.env.NEXT_PUBLIC_SUPABASE_URL!,
|
process.env.NEXT_PUBLIC_SUPABASE_URL!,
|
||||||
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!
|
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
|
||||||
|
{
|
||||||
|
auth: {
|
||||||
|
storage: cookieStorage,
|
||||||
|
flowType: "pkce",
|
||||||
|
},
|
||||||
|
}
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user