nextauthjs / next-auth

Authentication for the Web.
https://authjs.dev
ISC License
24.05k stars 3.33k forks source link

`useSession()` latency causes page load with the wrong user session info #9273

Closed khteh closed 9 months ago

khteh commented 9 months ago

Environment

System: OS: Linux 6.5 Ubuntu 23.10 23.10 (Mantic Minotaur) CPU: (20) x64 12th Gen Intel(R) Core(TM) i7-12800H Memory: 47.28 GB / 62.46 GB Container: Yes Shell: 5.2.15 - /bin/bash Binaries: Node: 21.2.0 - /usr/local/bin/node Yarn: 1.22.19 - /usr/local/bin/yarn npm: 10.2.3 - /usr/local/bin/npm Browsers: Chrome: 119.0.6045.199 npmPackages: next: 14.0.3 => 14.0.3 next-auth: ^4.24.5 => 4.24.5 react: ^18.2.0 => 18.2.0

Reproduction URL

https://github.com/nextauthjs/next-auth-example

Describe the issue

I am using next 14.0.3, react 18.2.0. A page in the application will call different backend service endpoints based on the presence / absence of user session object (whether the user is authenticated). However, there is a small window where the session is undefined during page refresh F5. This will cause wrong information displayed when the page is ready. Even when using useEffect to track changes in session object it would call the service endpoint twice and will have performance impact.

const { data: session, update } = useSession()

  const getProductsByBrand = async () => {
    const request = new GetProductsRequest()
    request.setBrandid((brandId as string) || '')
    const pageReq = new PageRequest()
    pageReq.setPage(page - 1)
    pageReq.setPagesize(pageSize)
    request.setPaging(pageReq)
    request.setLocale(router.locale || '')
    if (session?.user?.id) 
        request.setUserid(session!.user.id)
    const res = session?.user?.id ? 
    await ProductService.getProducts(request, getMetaData(session?.user?.accessToken)) : 
    await ProductService.getProductsPublic(request, {})
    if (res.getProductsList()?.length > 0) {
// show data
    }
    setLoading(false)
  }

  useEffect(() => {
    setLoading(true)
    getProducts()
  }, [brandId])

How to reproduce

const { data: session, update } = useSession()
  const getProductsByBrand = async () => {
    const request = new GetProductsRequest()
    request.setBrandid((brandId as string) || '')
    const pageReq = new PageRequest()
    pageReq.setPage(page - 1)
    pageReq.setPagesize(pageSize)
    request.setPaging(pageReq)
    request.setLocale(router.locale || '')
    if (session?.user?.id) 
        request.setUserid(session!.user.id)
    const res = session?.user?.id ? 
    await ProductService.getProducts(request, getMetaData(session?.user?.accessToken)) : 
    await ProductService.getProductsPublic(request, {})
    if (res.getProductsList()?.length > 0) {
// show data
    }
    setLoading(false)
  }

  useEffect(() => {
    setLoading(true)
    getProducts()
  }, [brandId])

Expected behavior

consistent session data

balazsorban44 commented 9 months ago

https://github.com/nextauthjs/next-auth-example is not a valid reproduction, it's just a link to our official example.

So it's hard to tell what the actual issue is.

 it would call the service endpoint twice

This might be https://nextjs.org/docs/pages/api-reference/next-config-js/reactStrictMode which is intentional. See the docs for clarification.