next-authnext.js14

useSession always returns empty user object after authentication


I am trying to implement Auth.js in my Next.js project and I managed to make the login work but when I try to access the user data from the session the user object is always empty even tho the session says authenticated and has an expiration date.

I mainly followed the official docs to set it up. Here is the code I have in auth.ts:

export const { handlers, signIn, signOut, auth } = NextAuth({
  providers: [
    Credentials({
        credentials: {
          email: {},
          password: {},
        },
        authorize: async (credentials) => {
          let data = {
            email: credentials.email as string,
            password: credentials.password as string,
          }

          const user = await AuthService.login(data)

          console.log('the user', user)
   
          return user
        },
    }),
  ],
})

When I perform a login, it all works fine and the user variable shows with all the user data in the console.log I have there. I made an AuthProvider component where I import the auth method of the configuration above to get the session data:

import { SessionProvider } from "next-auth/react";
import { auth } from "@/lib/auth";

export interface Props {
    children: React.ReactNode;
}

export default async function AuthProvider({ children }: Props) {
    const session = await auth();

    return (
        <SessionProvider session={session}>
            {children}
        </SessionProvider>
    )
}

I use the component to wrap the children of my main layout.tsx file like so:

export default async function RootLayout({
  return (
      <AuthProvider>
        {children}
      </AuthProvider>
  );
}

All well and good, now here is where I run into an issue, I have a UserPanel component where I want to show the info from the session. I have it setup like this:

 'use client'    
 export default function UserPanel() {
    const { data: session, status } = useSession();

    console.log('the session', session, status);
    return (
        <div>
            <p>{session.user.name}</p>
        </div>
    )
}

When I log in successfully the the info I get from useSession() returns and empty user object:

{
    "user": {},
    "expires": "2024-09-09T03:21:18.233Z"
}

It shows an expiration date and the status says authenticated. But none of the user data that my API returns is available.

How do I get the user data with useSession? Thanks in advance.


Solution

  • You need to add the session callback. and attach the necessary details that need to displayed on the client side session.

    import NextAuth from "next-auth";
    import Credentials from "next-auth/providers/credentials";
    
    export const { handlers, signIn, signOut, auth } = NextAuth({
      providers: [
        Credentials({
          credentials: {
            email: {},
            password: {},
          },
          authorize: async (credentials) => {
            let data = {
              email: credentials.email,
              password: credentials.password,
            };
    
            const user = await AuthService.login(data);
    
            console.log('the user', user);
    
            return user || null;
          },
        }),
      ],
      callbacks: {
        async session({ session, token, user }) {
          // Attach the user information to the session
          session.user = token.user;
          return session;
        },
        async jwt({ token, user }) {
          if (user) {
            token.user = user;
          }
          return token;
        },
      },
    });
    

    for adding additional paramerts to the user object create a new file called next-auth.d.ts

    import { DefaultSession, DefaultUser } from 'next-auth';
    import { JWT, DefaultJWT } from 'next-auth/jwt';
    
    declare module 'next-auth' {
      interface Session {
        user: {
          id: string;
          email: string;
          firstName: string;
          lastName: string;
          isAdmin: boolean;
        } & DefaultSession['user'];
      }
    
      interface User extends DefaultUser {
        firstName: string;
        lastName: string;
        isAdmin: boolean;
      }
    }
    
    declare module 'next-auth/jwt' {
      interface JWT extends DefaultJWT {
        email: string;
        firstName: string;
        lastName: string;
        isAdmin: boolean;
      }
    }
    

    And extend the current user, provided by default from your necessary parameters.