Next.js Discord

Discord Forum

In what cases can `session.user` be undefined?

Unanswered
GetPsyched posted this in #help-forum
Open in Discord
I've thought about this a ton but never really understood it

39 Replies

Of course, given that session is defined
Komondor
It depends on what auth provider you're using. You would need to set session.user in order for session.user to be defined
@Komondor It depends on what auth provider you're using. You would need to set session.user in order for session.user to be defined
So, say I'm defining a custom callback for session in the auth config, I can be sure to always have session.user?
Komondor
If you're setting it in that callback then yes
Awesome
Komondor
I'm assuming you're using NextAuth?
Yup
I can override user to be any type I want?
Komondor
Yep that callback will provide the session and the user. If using jwt then it will provide the jwt token instead of user. From either of those, you can set a user field in the session object
Also, is this a good way to set a user by fetching from a database? https://nextjs-forum.com/post/1213243382579863552#message-1213243382579863552
Komondor
@GetPsyched Also, is this a good way to set a user by fetching from a database? https://discord.com/channels/752553802359505017/1213243382579863552/1213243382579863552
I currently do the fetching inside my custom session callback and not using an adapter like this person did.
Unsure which practice is better since I didn't find any docs on it
Komondor
Fetching user from DB when inside callback is fine
If you're not using a db adapter then you won't have the user provided to you in that callback
Which is fine. It depends on your usecase
@Komondor If you're not using a db adapter then you won't have the user provided to you in that callback
Sorry but I didn't understand this. I'm getting the user from my current implementation:
export const authOptions: NextAuthOptions = {
  callbacks: {
    async session({ session }) {
      session.person = (await db.query.persons.findFirst({
        where: ({ email }, { eq }) => eq(email, session.user.email),
      }))!;
      return session;
    },
    ...
  },
  ...
};
declare module 'next-auth' {
  // A nicer way to assert that `email` will not be
  // undefined since we only use the Google provider as of now.
  interface User extends DefaultUser {
    email: string;
  }

  interface Session extends DefaultSession {
    person: InferSelectModel<typeof persons>;
    user: User;
  }
}
Moreover, should I do this?
declare module 'next-auth' {
  interface Session extends DefaultSession {
    user: InferSelectModel<typeof persons>;
  }
}

instead of this?
declare module 'next-auth' {
  interface Session extends DefaultSession {
    person: InferSelectModel<typeof persons>;
    user: User;
  }
}
Unsure if this might break things or not.
Komondor
I would limit the fields in your person object / user object in the session to just a few. I wouldn't stick the whole db object in there
@GetPsyched My person table has just 5-6 fields anyway.
Komondor
Right but in the future when you add more fields to the User model, you may forget that you're putting the entire user model in the session here. So I would specifically map just the few fields you need in the session, instead of putting the entire User model in there
Fair enough!
@GetPsyched Also, I though it would be good to cache this fetch since it'll be done each time the callback is called? ref: <https://github.com/nitkkr-dev/nitkkr/pull/147/commits/c4951df66f88c4615d71751f4f75aadc06417468>
Komondor
Meh I wouldn't worry about caching it if you have an index on email. I'd only worry about caching complex queries. How long does it stay cached until it expires?
Oof, seems like caching is still experimental in react
and you'll have to remember to expire the cache if you ever support users changing emails
Yeah, although due to the nature of my app, changing emails will never be a thing
@GetPsyched I'm assuming that's a yes to the former given it's just a few fields?
Bumping since I wanted a confirmation on this
@GetPsyched Bumping since I wanted a confirmation on this
Komondor
by all means let other people chime in for confirmation. Could you clarify exaclty what you are looking for confirmation on?
@GetPsyched Moreover, should I do this? tsx declare module 'next-auth' { interface Session extends DefaultSession { user: InferSelectModel<typeof persons>; } } instead of this? tsx declare module 'next-auth' { interface Session extends DefaultSession { person: InferSelectModel<typeof persons>; user: User; } }
WRT these bits of code, I wanted to ask whether it is safe to override the session.user type altogether since that's auto-populated depending on the provider that is used. For context, I'm using the Google provider and plan to implement a generic email provider
Might be worth noting that the 4 fields I'm getting in the existing User type, id, name, email, image are included in my custom type already.
but of course, feel free to wait for other opinions