more auth ree
This commit is contained in:
@@ -4,7 +4,6 @@ import {
|
|||||||
Outlet,
|
Outlet,
|
||||||
Scripts,
|
Scripts,
|
||||||
createRootRouteWithContext,
|
createRootRouteWithContext,
|
||||||
redirect,
|
|
||||||
} from "@tanstack/react-router";
|
} from "@tanstack/react-router";
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import { DefaultCatchBoundary } from "@/components/DefaultCatchBoundary";
|
import { DefaultCatchBoundary } from "@/components/DefaultCatchBoundary";
|
||||||
@@ -133,15 +132,6 @@ export const Route = createRootRouteWithContext<{
|
|||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (error instanceof Response && error.status === 440) {
|
|
||||||
console.log('__root beforeLoad: Session needs refresh, redirecting');
|
|
||||||
const from = encodeURIComponent(location.pathname + location.search);
|
|
||||||
throw redirect({
|
|
||||||
to: "/refresh-session",
|
|
||||||
search: { redirect: from }
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
console.error('__root beforeLoad error:', error);
|
console.error('__root beforeLoad error:', error);
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
@@ -152,6 +142,32 @@ export const Route = createRootRouteWithContext<{
|
|||||||
function RootComponent() {
|
function RootComponent() {
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
ensureSuperTokensFrontend();
|
ensureSuperTokensFrontend();
|
||||||
|
|
||||||
|
if (typeof window !== 'undefined') {
|
||||||
|
const cookies = document.cookie.split(';');
|
||||||
|
const accessTokenCookies = cookies.filter(c => c.trim().startsWith('sAccessToken='));
|
||||||
|
|
||||||
|
if (accessTokenCookies.length > 1) {
|
||||||
|
console.warn(`[Root] Found ${accessTokenCookies.length} duplicate sAccessToken cookies - clearing all SuperTokens cookies`);
|
||||||
|
|
||||||
|
const cookieNames = ['sAccessToken', 'sRefreshToken', 'sIdRefreshToken', 'sFrontToken'];
|
||||||
|
const cookieDomain = (window as any).__COOKIE_DOMAIN__ || undefined;
|
||||||
|
|
||||||
|
cookieNames.forEach(name => {
|
||||||
|
document.cookie = `${name}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;`;
|
||||||
|
|
||||||
|
if (cookieDomain) {
|
||||||
|
document.cookie = `${name}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/; domain=${cookieDomain}`;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log('[Root] Cleared duplicate cookies - page will reload to establish fresh session');
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
window.location.reload();
|
||||||
|
}, 100);
|
||||||
|
}
|
||||||
|
}
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -56,21 +56,8 @@ export const fetchMe = createServerFn()
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (error?.message === "SESSION_REFRESH_REQUIRED") {
|
if (error?.message === "SESSION_REFRESH_REQUIRED") {
|
||||||
logger.info("FetchMe: Session refresh required (server function)");
|
logger.info("FetchMe: Session refresh required - returning empty auth (client will handle cleanup)");
|
||||||
throw new Response(
|
return { user: undefined, roles: [], metadata: {}, phone: undefined };
|
||||||
JSON.stringify({
|
|
||||||
error: "SESSION_REFRESH_REQUIRED",
|
|
||||||
message: "Session needs to be refreshed",
|
|
||||||
shouldRetry: true
|
|
||||||
}),
|
|
||||||
{
|
|
||||||
status: 440,
|
|
||||||
headers: {
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
"X-Session-Expired": "true"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (error?.message === "Unauthenticated") {
|
if (error?.message === "Unauthenticated") {
|
||||||
|
|||||||
@@ -10,32 +10,14 @@ export async function getSessionForStart(request: Request, options?: { sessionRe
|
|||||||
if (cookieHeader) {
|
if (cookieHeader) {
|
||||||
const tokens = cookieHeader.match(/sAccessToken=([^;]+)/g);
|
const tokens = cookieHeader.match(/sAccessToken=([^;]+)/g);
|
||||||
if (tokens && tokens.length > 1) {
|
if (tokens && tokens.length > 1) {
|
||||||
logger.warn(`Detected ${tokens.length} duplicate sAccessToken cookies, cleaning up`);
|
logger.warn(`Detected ${tokens.length} duplicate sAccessToken cookies - session is broken, forcing cleanup`);
|
||||||
|
|
||||||
const parsedTokens = tokens.map(tokenStr => {
|
return {
|
||||||
const token = tokenStr.replace('sAccessToken=', '');
|
hasToken: false,
|
||||||
try {
|
needsRefresh: true,
|
||||||
const payload = JSON.parse(Buffer.from(token.split('.')[1], 'base64').toString());
|
error: 'DUPLICATE_COOKIES_DETECTED',
|
||||||
return { token, exp: payload.exp, iat: payload.iat };
|
duplicateCount: tokens.length
|
||||||
} catch (e) {
|
};
|
||||||
logger.error('Failed to parse token', e);
|
|
||||||
return { token, exp: 0, iat: 0 };
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
parsedTokens.sort((a, b) => b.exp - a.exp);
|
|
||||||
const freshestToken = parsedTokens[0];
|
|
||||||
|
|
||||||
logger.info(`Using freshest token: exp=${freshestToken.exp}, iat=${freshestToken.iat}`);
|
|
||||||
|
|
||||||
const cleanedCookie = cookieHeader
|
|
||||||
.split(';')
|
|
||||||
.filter(c => !c.trim().startsWith('sAccessToken='))
|
|
||||||
.join(';') + `; sAccessToken=${freshestToken.token}`;
|
|
||||||
|
|
||||||
const cleanedHeaders = new Headers(request.headers);
|
|
||||||
cleanedHeaders.set('cookie', cleanedCookie);
|
|
||||||
request = new Request(request, { headers: cleanedHeaders });
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -23,9 +23,6 @@ export async function ensureServerQueryData<TData>(
|
|||||||
if (error?.options?.to && error?.options?.statusCode) {
|
if (error?.options?.to && error?.options?.statusCode) {
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
if (error instanceof Response && error.status === 440) {
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,11 +34,6 @@ export const toServerResult = async <T>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (error instanceof Response && error.status === 440) {
|
|
||||||
logger.info('toServerResult: Re-throwing 440 Response for session refresh');
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
|
|
||||||
const duration = Date.now() - startTime;
|
const duration = Date.now() - startTime;
|
||||||
logger.error('Server Fn Error', error);
|
logger.error('Server Fn Error', error);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user