Next-auth: Session with all null values on user with jwt, how does it work ?

Created on 17 Sep 2020  Â·  10Comments  Â·  Source: nextauthjs/next-auth

Your question
I'm using JWT, the object return by useSession is always empty (it exists, but with all null values on the user object ex: { name: null, email: null, picture: null } even tho the debug logs everything correctly.

What are you trying to do
I customized the callbacks to return the user, I expected it to this by default, it took me a while to realize how to to it

this is my code

import NextAuth, { InitOptions } from 'next-auth'
import Adapters from 'next-auth/adapters'
import Providers from 'next-auth/providers'
import { prismaClient } from '../../../../graphql/configs/prismaClient'

const options: any = {
  providers: [
    Providers.Facebook({
      clientId: process.env.FACEBOOK_CLIENT_ID,
      clientSecret: process.env.FACEBOOK_CLIENT_SECRET,
    }),
  ],
  database: process.env.DATABASE_URL,
  jwt: {
    encryption: true,
    // secret: process.env.AUTH_SECRET,
  },
  session: {
    jwt: true,
    updateAge: 1000 * 60 * 60 * 24,
  },
  secret: process.env.AUTH_SECRET,
  useSecureCookies: process.env.NODE_ENV === 'production',
  adapter: Adapters.Prisma.Adapter({ prisma: prismaClient }),
  debug: true,
 // these callbacks are what makes the user work as expected, otherwise it returns empty values
  callbacks: {
    session(session, payload) {
      if (payload.account) session.user = payload.account
      return session
    },
    jwt(token, account, user, userInfo) {
      if (userInfo) token.account = userInfo
      return token
    },
  },
}

export default (req, res) => {
  return NextAuth(req, res, options)
}

// _app.tsx
 <Provider session={pageProps.session} options={{ keepAlive: TEN_MINUTES, clientMaxAge: ONE_WEEK }}>
        <Component {...pageProps} />
   </Provider>

// index.tsx

function Home() {
  const { data, loading: queryLoading } = useMyQueryQuery({ ssr: true, fetchPolicy: 'cache-first' })
  const [session, sessionLoading] = useSession()
  return (
    <Layout>
      <Head>
        <title>Next.js × Nexus Todo App</title>
      </Head>
      {session && JSON.stringify(session)}
      {sessionLoading}
      <a href="/api/auth/signin">Sign in</a>
      <a href="/api/auth/signout">Sign out</a>
    </Layout>
  )
}

Feedback

  • [-] Found the documentation helpful // meh, kinda, the callbacks doc surely helped, but took me a while to realize I had to use them
  • [x] Found documentation but was incomplete
  • [] Could not find relevant documentation
  • [] Found the example project helpful
  • [x] Did not find the example project helpful // it didnt have callbacks, but worked fine appearently

Seems like a great library btw ! :D, I probably just misunderstood something I suppose

help wanted question

All 10 comments

Hi @Mautriz

Thanks for sharing your issue and config!

This should actually work out of the box for name, email and picture, as per the example:

https://next-auth-example.now.sh/api-example

Facebook API

I wonder what the trigger is for this issue.

Hi there! It looks like this issue hasn't had any activity for a while. It will be closed if no further activity occurs. If you think your issue is still relevant, feel free to comment on it to keep ot open. Thanks!

Hi there! It looks like this issue hasn't had any activity for a while. To keep things tidy, I am going to close this issue for now. If you think your issue is still relevant, just leave a comment and I will reopen it. (Read more at #912) Thanks!

@iaincollins I get the same issue and seems to be related with Prisma adapter. If I remove the adapter, everything works great without callback.

Here some tests with no user in database (pg) and no user in my Github App.

Test 1

JWT + Prisma:

 providers: [
    Providers.GitHub({
      clientId: process.env.GITHUB_ID,
      clientSecret: process.env.GITHUB_SECRET,
    }),
  ],
  secret: process.env.SECRET,
  // database: process.env.DATABASE_URL,
  adapter: Adapters.Prisma.Adapter({ prisma }),
  session: {
    jwt: true,
  },

Results:

  1. 1st signIn → Success: Session has data. JWT no data.
  2. 2nd signIn → Failure: Session has no data. JWT has no data.

Test 2

Session + Prisma

  // database: process.env.DATABASE_URL,
  adapter: Adapters.Prisma.Adapter({ prisma }),
  // session: {
  //  jwt: true,
  // },

Result: Success → Session has data.

Test 3

JWT + Typeorm:

   database: process.env.DATABASE_URL,
  // adapter: Adapters.Prisma.Adapter({ prisma }),
  session: {
    jwt: true,
  },

Result: Success → Session has data.

Conclusion

So JWT + Prisma AND isNewUser == false the token has no data. Any idea @iaincollins of why?

I found the error.

The function getUserByProviderAccountId from the Prisma adapter return a row from the Account table instead of the User table. So here the user variable do not contains the right data and the JWT payload can't be filled correctly.

Is it possible to have a v3.1.1 that fix this issue?

Cc @iaincollins & @balazsorban44.

in the Prisma adapter, this should fix the issue:

- return prisma[Account].findOne({ where: { compoundId: getCompoundId(providerId, providerAccountId) } })
+ const account = await prisma[Account].findOne({ where: { compoundId: getCompoundId(providerId, providerAccountId) } })
+ if (!account) { return null }
+ return prisma[User].findOne({ where: { id: account.userId } })

Hi, @ChristoRibeiro could you please create a PR with your recommended fix so it's easier to evaluate? Thank you!

The issue doesn't appear anymore on the canary branch and the deprecated prisma method findOne has been updated to findUnique. I'm not sur a PR is required. Do you plan to make a release soon @balazsorban44?

Yes, hopefully this month.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

iaincollins picture iaincollins  Â·  3Comments

ryanbahan picture ryanbahan  Â·  3Comments

loonskai picture loonskai  Â·  3Comments

iaincollins picture iaincollins  Â·  3Comments

MelMacaluso picture MelMacaluso  Â·  3Comments