1

I have the GoogleProvider working, and returning a valid session. But when I create a CredentialsProvider it isn't working.

The credentials provider successfully creates a user in the database with graphql. And I'm able to log the returned user at the bottom.

import { client } from '@/src/graphql/apollo-client'
import UserOperations from '@/src/graphql/operations/user'
import { CreateUserData, CreateUserInput } from '@/src/util/types'
import credentialsProvider from 'next-auth/providers/credentials'

export default CredentialsProvider({
  name: '',
  credentials: {
    email: { label: 'Username', type: 'text', placeholder: 'email' },
    password: { label: 'Password', type: 'password' }
  },
  async authorize(credentials, req) {
    const signUp = UserOperations.Mutations.signUp
    const response = await client.mutate<CreateUserData, CreateUserInput>({
      mutation: signUp,
      variables: {
        email: credentials?.email!,
        password: credentials?.password!
      }
    })
    const { data } = response
    const user = data

    console.log('the user data returned is ', user)

    if (user) {
      return user
    }
    return null
  }
})

I'm using that provider along side a GoogleProvider in [...nextauth].ts

import NextAuth from 'next-auth'
import GoogleProvider from 'next-auth/providers/google'
import { PrismaAdapter } from '@next-auth/prisma-adapter'
import { PrismaClient } from '@prisma/client'
import CredentialsProvider from './providers/credentials'

const prisma = new PrismaClient()

export default NextAuth({
  adapter: PrismaAdapter(prisma),
  providers: [

    credentialsProvider, //the credentials provider from above

    GoogleProvider({
      clientId: process.env.GOOGLE_CLIENT_ID as string,
      clientSecret: process.env.GOOGLE_CLIENT_SECRET as string
    })
  ],
  secret: process.env.JWT_SECRET,
  callbacks: {
    async session({ session, token, user }) {


  //here the google provider returns values, but the credentials provider does not. 
      console.log('session ', session, ' user ', user)

      return {
        ...session,
        user: { ...session.user, ...user } // combine the session and db user
      }
    }
  }
})

Inside of async session you can see I have another console log. When using the google provider I can log the session and user, but I'm getting session:null and user:null with the credentials provider.

So I'm not sure where session gets set with Credentials Provider or what other steps I may be missing.

Happy to provide any other files if they help, but I thought this would be simplest to start.

Help is much appreciated, thanks.

EDIT - It looks like someone was able to use credentials provider along side Prisma adapter here. I tried adding the encode/ decode token block that they used, but still no luck.

I may be confused about how JWT fits into the picture.

Yulian Kraynyak
  • 369
  • 4
  • 11
Louis Sankey
  • 481
  • 8
  • 26
  • can you try `return Promise.resolve(user)` – Yilmaz Feb 13 '23 at 22:23
  • thanks for the suggestion, no luck with that however. – Louis Sankey Feb 13 '23 at 23:17
  • 1
    you did not implement the callbacks, for credentials provider or you did not provide on the question? – Yilmaz Feb 13 '23 at 23:20
  • @yilmax, that must be what I am missing, thank you for point it out. I must have missed doing that somehow. – Louis Sankey Feb 13 '23 at 23:25
  • It might not be possible with Prisma Adapter, unfortunately --- https://stackoverflow.com/questions/70474736/nextauth-credential-provider-with-prisma-adapter-in-next12-does-nothing – Wesley LeMahieu Feb 14 '23 at 02:01
  • many thanks, I had come across that. it appears the documentation he references has changed however, I don't see any mentioned that they can't be used together, but I might be missing it (or it might just be absent). In the github link he referenced the poster said they got them to work together in a sandbox. Frustrating. – Louis Sankey Feb 14 '23 at 02:21

1 Answers1

0

I was able to get this to work!! I just use strategy 'jwt', and then in the jwt callback I had access to the user and token. So I could assign the user to user.token and then the token is available in the session callback.

So with other providers like google I could access user and session directly in the session callback. But with credentials I had to go through the token parameter.

import NextAuth from 'next-auth'
import GoogleProvider from 'next-auth/providers/google'
import { PrismaAdapter } from '@next-auth/prisma-adapter'
import { PrismaClient } from '@prisma/client'
import credentialsProvider from '../../../providers/credentials'

const prisma = new PrismaClient()

export default NextAuth({
  adapter: PrismaAdapter(prisma),
  session: {
    strategy: 'jwt'
  },
  providers: [
    credentialsProvider,
    GoogleProvider({
      clientId: process.env.GOOGLE_CLIENT_ID as string,
      clientSecret: process.env.GOOGLE_CLIENT_SECRET as string
    })
  ],
  secret: process.env.JWT_SECRET,
  callbacks: {
    jwt: async ({ token, user }) => {
      user && (token.user = user)
      return token
    },
    //whatever value we return here will be the value of the next-auth session
    async session({ session, token, user }) {
      return {
        ...session,
        user: { ...session.user, ...user, ...token.user! } // combine the session and db user
      }
    }
  }
})
Yulian Kraynyak
  • 369
  • 4
  • 11
Louis Sankey
  • 481
  • 8
  • 26