feat: optimize NextAuth session and token management

- Added global session caching to reduce API calls
- Improved token refresh logic with expiry check
- Implemented 5-minute session caching mechanism
- Added type declarations for global session cache
This commit is contained in:
swve 2025-01-25 13:51:15 +01:00
parent 6edf02b92d
commit 31e8eaf0b5

View file

@ -9,6 +9,16 @@ import { getResponseMetadata } from '@services/utils/ts/requests'
import CredentialsProvider from 'next-auth/providers/credentials' import CredentialsProvider from 'next-auth/providers/credentials'
import GoogleProvider from 'next-auth/providers/google' import GoogleProvider from 'next-auth/providers/google'
// Add type declarations at the top of the file
declare global {
var sessionCache: {
[key: string]: {
data: any;
timestamp: number;
};
};
}
export const isDevEnv = LEARNHOUSE_TOP_DOMAIN == 'localhost' ? true : false export const isDevEnv = LEARNHOUSE_TOP_DOMAIN == 'localhost' ? true : false
export const nextAuthOptions = { export const nextAuthOptions = {
@ -67,7 +77,7 @@ export const nextAuthOptions = {
async jwt({ token, user, account }: any) { async jwt({ token, user, account }: any) {
// First sign in with Credentials provider // First sign in with Credentials provider
if (account?.provider == 'credentials' && user) { if (account?.provider == 'credentials' && user) {
token.user = user token.user = user;
} }
// Sign up with Google // Sign up with Google
@ -76,17 +86,20 @@ export const nextAuthOptions = {
user.email, user.email,
'google', 'google',
account.access_token account.access_token
) );
let userFromOAuth = await getResponseMetadata(unsanitized_req) let userFromOAuth = await getResponseMetadata(unsanitized_req);
token.user = userFromOAuth.data token.user = userFromOAuth.data;
} }
// Refresh token // Refresh token only if it's close to expiring (5 minutes before expiry)
// TODO : Improve this implementation if (token?.user?.tokens) {
if (token?.user?.tokens) { const tokenExpiry = token.user.tokens.expiry || 0;
const fiveMinutes = 5 * 60 * 1000;
if (Date.now() + fiveMinutes >= tokenExpiry) {
const RefreshedToken = await getNewAccessTokenUsingRefreshTokenServer( const RefreshedToken = await getNewAccessTokenUsingRefreshTokenServer(
token?.user?.tokens?.refresh_token token?.user?.tokens?.refresh_token
) );
token = { token = {
...token, ...token,
user: { user: {
@ -94,21 +107,40 @@ export const nextAuthOptions = {
tokens: { tokens: {
...token.user.tokens, ...token.user.tokens,
access_token: RefreshedToken.access_token, access_token: RefreshedToken.access_token,
expiry: Date.now() + (60 * 60 * 1000), // 1 hour from now
}, },
}, },
} };
} }
return token }
return token;
}, },
async session({ session, token }: any) { async session({ session, token }: any) {
// Include user information in the session // Include user information in the session
if (token.user) { if (token.user) {
let api_SESSION = await getUserSession(token.user.tokens.access_token) // Cache the session for 5 minutes to avoid frequent API calls
session.user = api_SESSION.user const cacheKey = `user_session_${token.user.tokens.access_token}`;
session.roles = api_SESSION.roles let cachedSession = global.sessionCache?.[cacheKey];
session.tokens = token.user.tokens
if (cachedSession && Date.now() - cachedSession.timestamp < 5 * 60 * 1000) {
return cachedSession.data;
}
let api_SESSION = await getUserSession(token.user.tokens.access_token);
session.user = api_SESSION.user;
session.roles = api_SESSION.roles;
session.tokens = token.user.tokens;
// Cache the session
if (!global.sessionCache) {
global.sessionCache = {};
}
global.sessionCache[cacheKey] = {
data: session,
timestamp: Date.now()
};
} }
return session return session;
}, },
}, },
} }