"use client" import { usePathname, useSearchParams } from "next/navigation" import { SessionProvider, useSession } from "next-auth/react" import { useEffect, useMemo, useRef } from "react" import { MAX_KEEP_ALIVE_TIME_IN_MINUTES, PRE_REFRESH_TIME_IN_SECONDS, } from "@/constants/auth" /** * Keeps the access token alive by proactively refreshing it * */ export default function TokenRefresher() { return ( ) } export function SessionRefresher() { const session = useSession() const pathname = usePathname() const searchParams = useSearchParams() const timeoutId = useRef>(undefined) // Simple inactivity control. Reset when the URL changes. const stopPreRefreshAt = useMemo( () => Date.now() + MAX_KEEP_ALIVE_TIME_IN_MINUTES * 60 * 1000, // eslint-disable-next-line react-hooks/exhaustive-deps [pathname, searchParams] ) useEffect(() => { if (timeoutId.current) { clearTimeout(timeoutId.current) } if (!session.data?.token.expires_at) { return } const refreshIn = session.data.token.expires_at - Date.now() - PRE_REFRESH_TIME_IN_SECONDS * 1000 timeoutId.current = setTimeout( async () => { if (stopPreRefreshAt > Date.now()) { await session.update({ doRefresh: true }) } }, // If the token has already expired `refreshIn` will be // negative, and we will refresh immediately (in 1 ms) Math.max(refreshIn, 1) ) return () => clearTimeout(timeoutId.current) // eslint-disable-next-line react-hooks/exhaustive-deps }, [session.data?.token.expires_at, stopPreRefreshAt]) return null }