From dc858227fa64f7a3a1160c6a1ed0b34965effa8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi?= Date: Mon, 6 Jan 2025 03:15:01 +0100 Subject: [PATCH] feat: integrate session management with AppWrapper and update axios interceptor for token handling --- src/app/components/AppWrapper.tsx | 5 ++++- src/app/layout.tsx | 7 +++++-- src/app/lib/axios.ts | 4 ++++ src/app/lib/stringUtils.ts | 3 --- src/authOptions.ts | 5 ++++- 5 files changed, 17 insertions(+), 7 deletions(-) delete mode 100644 src/app/lib/stringUtils.ts diff --git a/src/app/components/AppWrapper.tsx b/src/app/components/AppWrapper.tsx index 36e0cc5..f2224ee 100644 --- a/src/app/components/AppWrapper.tsx +++ b/src/app/components/AppWrapper.tsx @@ -1,16 +1,19 @@ "use client"; import { NextUIProvider } from "@nextui-org/react"; +import { Session } from "next-auth"; import { SessionProvider } from "next-auth/react"; import { ThemeProvider as NextThemesProvider } from "next-themes"; export default function AppWrapper({ + session, children, }: { + session: Session | null; children: React.ReactNode; }) { return ( - + {children} diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 35157e7..72bd773 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -1,15 +1,18 @@ +import { getSession } from "@/authOptions"; import AppWrapper from "./components/AppWrapper"; import "./globals.css"; -export default function RootLayout({ +export default async function RootLayout({ children, }: { children: React.ReactNode; }) { + const session = await getSession() + return ( - {children} + {children} ); diff --git a/src/app/lib/axios.ts b/src/app/lib/axios.ts index 7e5437f..bedf29a 100644 --- a/src/app/lib/axios.ts +++ b/src/app/lib/axios.ts @@ -12,19 +12,23 @@ export const axiosInstance = axios.create({ }); axiosInstance.interceptors.request.use(async (config) => { + // If the access token is still valid, use it if (tokenExpirationAt && moment().isBefore(tokenExpirationAt)) { config.headers.Authorization = `Bearer ${cachedAccessToken}`; return config; } + // Otherwise, get a new access token const session = await getSession(); if (!session) { throw new Error("User is not authenticated"); } + // Cache the new access token cachedAccessToken = session.accessToken; tokenExpirationAt = moment(session.accessTokenExpires); + // Use the new access token config.headers.Authorization = `Bearer ${cachedAccessToken}`; return config; }); diff --git a/src/app/lib/stringUtils.ts b/src/app/lib/stringUtils.ts deleted file mode 100644 index 9aed25d..0000000 --- a/src/app/lib/stringUtils.ts +++ /dev/null @@ -1,3 +0,0 @@ -export const UppercaseFirstLetter = (str: string) => { - return str.slice(0, 1).toLocaleUpperCase() + str.slice(1); -}; diff --git a/src/authOptions.ts b/src/authOptions.ts index 3e6f86f..965f06f 100644 --- a/src/authOptions.ts +++ b/src/authOptions.ts @@ -1,9 +1,10 @@ import axios from "axios"; import moment from "moment"; -import { AuthOptions, Session } from "next-auth"; +import { AuthOptions, getServerSession, Session } from "next-auth"; import { JWT } from "next-auth/jwt"; import jsonwebtoken from "jsonwebtoken"; import { JWTDecoded } from "./app/types/next-auth"; +import { cache } from "react"; moment.locale("fr"); @@ -120,3 +121,5 @@ const refreshAccessToken = async (token: JWT): Promise => { refreshToken: response.data.refresh_token, }; }; + +export const getSession = cache(() => getServerSession());