-
-
Notifications
You must be signed in to change notification settings - Fork 3.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Is it possible to prevent api/auth/session from being called multiple times? #6630
Comments
You should not use |
@balazsorban44 but in my question I explained that I use getSession, at no point did I comment about useSession. Can you please reopen the issue? :c |
I need my glasses... 👀 This is likely still not a NextAuth.js bug for what it's worth, but how you use axios, I assume.
|
Hi @frontlearner28 I am facing the same issue as you, did you find out have you can reduce the api requests every time you use getSession() ? |
Hi @balazsorban44 I understand that getSession is only used to get session info but is there a better way to use it? In client side I need to send the access token with many requests. With every request I need to call the method getSession() to get the Auth token, I don't have any other way in mind. Can I save the session data locally in the browser or something? |
@Ali-hd did u found any solution to this. @balazsorban44 can u suggest some better approach or link to something that can help here? |
You can for example proxy the API requests through the Next.js backend and attach the session there. You can get the session server-side without extra network trips. |
Well actually, api/auth/session is basically the same. So from client side we are calling proxy api then it will be calling the api just like /api/auth/session as both of the things will be at next.js backend. So either call api/auth/session and get token and then call the actual api or call the proxy api. I think in 2nd approch we can save 1 network trip from client side. |
TL;DR; So actually I was implementing it for 2 things. First is openapi-fetch client to attach auth on every request similar to axios and is already implemented using the getSession() which was causing the problem and cant make it hook as it might break and will have to do refactor since it is not react component. Second is to check permission access for specific function of application where I need to compare permission required to access that resource vs the session permissions. So I ended up using state management library "zustand" note that u should not use it to share state across server component and client component. So using their official document for how to implement auth in client component (basically call auth() and get session, then take that session and pass it along with session provider which is wrapping the client component, and use useSession()). I used this trick on main layout file and then just in client component I set the state of zustand. This allowed me to access latest value of zustand state everywhere even in non-component file. So u can implement this approach. Thanks for help guys! |
I saw this issue after migrating to V5, but if it's the issue of next-auth then I can rest assured, the team need time to refactor |
I'm using V5 and this keeps happening.. session and jwt callbacks happening 6 times one after another :/ I tried everything |
Yeah. I am rethinking whether to use this or not. The session callback api get's called so many times. Even if i have not used useSession() hook |
Having the same issue, for now I am caching the data I received to prevent multiple api calls based on useSession, but everytime i use useSession, the session calls are increasing rapidly. |
i think if u use the session provider in specific components that u need u can tackle this issue even without caching it. |
Try this solution |
If anyone stumbles upon it I solved it by fetching the session in main layout of my app and passing it to a component which sets it in a zustand store. I am not calling useSession anymore as it seems to be the culprit. |
useSession with the sessionProvider is the culprit if u use getServerSession it doesnt give the issue |
Why is this closed? It has not been solved ... |
Does any found a optimal way to do it ? without repeating session like multiple times. |
This comment has been minimized.
This comment has been minimized.
Do we have a solution yet ? |
Jesus. That /session is on rampage now (14 times call on just watching the page, and switch tabs) |
Got this issue on |
looks like they decreased in |
As I see this is still a problem for some people. I am checking session once on in my RootLayout. const RootLayout = async (props: LayoutProps): Promise<JSX.Element> => {
//...
const session = (await auth()) as DbSession | null;
return (
<html>
{/* ... */}
<SessionStoreProvider session={session} />
{/* ... */}
</html>
);
} In that component I am using this session to set it into a global zustand store. I am also running fetch (with 'use client';
import { memo, useEffect } from 'react';
import useSWR, { mutate } from 'swr';
import { setSession } from '@/store/auth/actions/session';
import { fetcher } from '@/utils/api';
import type { DbSession } from '../../auth';
const SessionStoreProvider = (
props: SessionStoreProviderProps,
): React.JSX.Element => {
useEffect(() => {
setSession(props.session);
}, [props.session]);
const { data, isLoading } = useSWR<DbSession | null>(
'/api/auth/session',
fetcher,
{
refreshInterval: 300000,
},
);
useEffect(() => {
if (isLoading) return;
setSession(data ?? null);
}, [data, isLoading]);
return <></>;
};
export default memo(SessionStoreProvider);
export const mutateSession = (): Promise<unknown> =>
mutate('/api/auth/session');
type SessionStoreProviderProps = {
session: DbSession | null;
}; You can also update session at any point by calling Fetching the session client-side is done through zustand api instead of next-auth api. With this I get complete control over the amount of calls to /api/auth/session endpoint. Hope this helps. |
For anyone reading this, this is not a bug. Depending on your code, it could happen for multiple reasons. If anyone would like me to dissect their exact usecase a bit more and see if we can document gotchas better or fix any potential bugs, please open a new bug report with a reproduction. This issue has been closed, and we generally don't monitor these. The OP's question about axios should have been answered, I'm seeing diverse questions in follow-up comments now. Here is some of the general advice:
Solution: https://react.dev/reference/react/cache We are considering to add this by default
With the App Router, we would however recommend relying on I hope this helps! 🙏 |
@balazsorban44 could you expound on the react/cache solution please? |
// contexts/CashedSessionContext.tsx
import { createContext, useContext, useState, useEffect, ReactNode } from 'react'
import { useSession } from 'next-auth/react'
import { Session } from 'next-auth'
import { setupAxiosInterceptors } from '@/api/utils/axios'
const CachedSessionContext = createContext<Session | null>(null)
interface SessionProviderProps {
children: ReactNode
}
export function CachedSessionProvider({ children }: SessionProviderProps) {
const { data: session } = useSession()
const [cachedSession, setCachedSession] = useState<Session | null>(session)
useEffect(() => {
if (session) {
setCachedSession(session)
setupAxiosInterceptors(session) // HEEEERE
}
}, [session])
return (
<CachedSessionContext.Provider value={cachedSession}>
{children}
</CachedSessionContext.Provider>
)
}
export function useCachedSession() {
return useContext(CachedSessionContext)
} axios instance // utils/axios.ts
export const privateAxiosInstance = axios.create({
baseURL: API_URL,
withCredentials: true,
headers: {
'Content-Type': 'application/json',
},
})
export function setupAxiosInterceptors(session: Session) {
privateAxiosInstance.interceptors.request.use(
(config) => {
if (session?.accessToken) {
config.headers.Authorization = `Bearer ${session.accessToken}`
}
return config
},
(error) => {
const formattedError = {
status: error.response?.status,
message: error.response?.data?.message || error.message,
}
return Promise.reject(formattedError)
}
)
} now you can use |
On <SessionProvider session={session} refetchOnWindowFocus={false}>
{children}
</SessionProvider> However, I haven’t fully explored whether this workaround could cause any side effects or regressions in the app. We can also add an |
Question 💬
Currently, I use getSession() in my Axios interceptor, to control valid session. The problem is that the session is being called multiple times on pages with many API calls, increasing my page load time too much.
Is there any way to prevent this?
How to reproduce ☕️
To reproduce the problem, use getSession in an Axios interceptor and execute many calls on one page
Contributing 🙌🏽
Yes, I am willing to help answer this question in a PR
The text was updated successfully, but these errors were encountered: