I cannot get ID from session in GET method in Next.js 14

29 views Asked by At

I have created an api route to handle the getAllAddresses that the currently logged in user has created. But I only get an empty array. I imagined that req cannot get the ID of the currently logged in user. I checked nextauth configuration and I got the ID.

To be more certain, I console.log the session configuration on nextauth and get the ID as follows:

  ~ session ~ session: {
  user: {
    name: 'Nhung Nguyen',
    email: '[email protected]',
    image: 'https://lh3.googleusercontent.com/a/ACg8ocLg8TfKh72d8RDiUO9xIxR7CTgR4e6hU8WpwTtlXHEDEIg=s96-c',
    id: '65ff0b9c80353678f60e337a'
  },
  expires: '2024-04-27T13:26:30.889Z'
}

But on the api route handle getAllAddresses, the session I receive only has name, email, image, no ID. This is my log at api route handle getAllAddresses:

 ~ GET ~ session: {
  user: {
    name: 'Nhung Nguyen',
    email: '[email protected]',
    image: 'https://lh3.googleusercontent.com/a/ACg8ocLg8TfKh72d8RDiUO9xIxR7CTgR4e6hU8WpwTtlXHEDEIg=s96-c'
  }
}

This is my code in api/auth/[...nextauth]/route.js

    const handler = NextAuth({
    providers: [
        CredentialsProvider({
            name: 'credentials',
            credentials: {},
            async authorize(credentials, req) {
                await connect()

                const user = await User.findOne({ email: credentials.email })

                if (!user) {
                    throw new Error('Đăng nhập không hợp lệ!')
                }

                const comparePassword = await bcrypt.compare(credentials.password, user.password)

                if (!comparePassword) {
                    throw new Error('Đăng nhập không hợp lệ!')
                }

                return user
            }
        }),
        GoogleProvider({
            clientId: process.env.GOOGLE_CLIENT_ID,
            clientSecret: process.env.GOOGLE_CLIENT_SECRET
        }),
    ],
    session: {
        strategy: 'jwt'
    },
    pages: {
        signIn: '/login'
    },
    secret: process.env.NEXTAUTH_SECRET,
    callbacks: {
        async signIn({ profile, account }) {
            if (account.provider === 'google') {
                try {
                    await connect()
                    let user = await User.findOne({ email: profile.email })
                    if (!user) {
                        user = await User.create({
                            email: profile.email,
                            name: profile.name,
                            avatar: profile.image,
                            wishlist: [],
                            cart: [],
                            orders: [],
                            products: []
                        })
                    }
                    return user

                } catch (error) {
                    console.log(error)
                }
            }
            return true
        },
        async jwt({ token, user }) {
            user && (token.user = user)

            return token
        },
        async session({ session }) {
            const sessionUser = await User.findOne({ email: session.user.email })
            // console.log(' ~ session ~ sessionUser:', sessionUser)

            session.user.id = sessionUser._id.toString()
            console.log(' ~ session ~ session.user.id:', session.user.id)

            console.log(' ~ session ~ session:', session)

            return session
        }
    }
})

export { handler as GET, handler as POST }

And this is my code at api route handle getAllAddresses

export async function GET(req) {
    try {
        const session = await getServerSession({ req })
        console.log(' ~ GET ~ session:', session)

        if (!session) {
            return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
        }
        const getAllAddresses = await Address.find({ userID: session.user.id })

        if (getAllAddresses) {
            return NextResponse.json({
                success: true,
                data: getAllAddresses,
            });
        } else {
            return NextResponse.json({
                success: false,
                message: "failed to get addresses ! Please try again",
            });
        }
    } catch (error) {
        console.error('Error fetching user addresses:', error)
        return NextResponse.json({ error: 'Internal Server Error' }, { status: 500 })
    }
}
2

There are 2 answers

0
Arash Jahan Bakhshan On BEST ANSWER

I searched more in the Next Auth documentation. I found out that you are using the getServerSession incorrectly. In V4 while you are using the App router, you must pass only the next auth options to this function. More information can be found here (https://next-auth.js.org/configuration/nextjs#in-app-router)

However, I will give you en example which you can use it right away in your code.

First of all, you should export the config of the Next Auth. Like this:

// app/api/auth/[...nextauth]/route.js
export const authOptions = {
    providers: [...],
    session: ...,
    ...
}

const handler = NextAuth(authOptions)

export { handler as GET, handler as POST }

After that, you can create a util file called auth.js or whatever and put this function in it:

import {authOptions} from "app/api/[...nextauth]/route.js"

export const auth = () => getServerSession(authOptions)

Finally, you can import this function wherever you want and call it:

export const POST = async () => {
   const session = await auth();

   ...
}
0
Neer Amrutia On

You must provide a session callback :

callbacks: {
  async session({ session, token, user }) {
    // Send properties to the client, like an access_token and user id from a provider.
    session.accessToken = token.accessToken
    session.user.id = token.id
    
    return session
  }
}

and add the id to session from use or token object. ref : https://next-auth.js.org/configuration/callbacks