import { createCookieSessionStorage, Session } from "@remix-run/node"; import { isProduction } from "./utils/get-env"; const isProd = process.env.NODE_ENV === "production"; const sessionSecret = process.env.REMIX_SECRET; // Fail closed: never ship a guessable signing secret to production. A signed // cookie with a known secret can be forged, allowing session tampering. if (isProd && !sessionSecret) { throw new Error( "REMIX_SECRET environment variable must be set in production." ); } // export the whole sessionStorage object export const sessionStorage = createCookieSessionStorage({ cookie: { name: "vitrown_session", // use name you want here sameSite: "lax", // this helps with CSRF path: "/", // remember to add this so the cookie will work in all routes httpOnly: true, // for security reasons, make this cookie http only maxAge: 60 * 60 * 24 * 30, // 30 days (matches refresh-token lifetime) // Dev-only fallback; production is guarded by the check above. secrets: [sessionSecret ?? "dev-only-insecure-secret"], // Send only over HTTPS in production (NODE_ENV is the reliable server signal). secure: isProd || isProduction(), }, }); export const { getSession, commitSession, destroySession } = sessionStorage; export interface UserTrackerSessionType { token: string; session: Session; } // Helper function to check if access_token is expired (1 week) export function isAccessTokenExpired(tokenTimestamp: number): boolean { const oneWeekInMs = 7 * 24 * 60 * 60 * 1000; // 7 days in milliseconds const currentTime = Date.now(); return currentTime - tokenTimestamp > oneWeekInMs; } // Helper function to check if refresh_token is expired (1 month) export function isRefreshTokenExpired(tokenTimestamp: number): boolean { const oneMonthInMs = 30 * 24 * 60 * 60 * 1000; // ~30 days in milliseconds const currentTime = Date.now(); return currentTime - tokenTimestamp > oneMonthInMs; }