question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Credentials Provider Not Firing Session Callback

See original GitHub issue

Description 🐜

Hello,

I’m having trouble with using Credentials Provider where it’s not firing the session callback. I’ve logged the whole process from signin and output with logger functionality.

I’m not sure if it’s my […nextauth] setting or it’s a bug within next-auth and prisma adapter.

Can provide the repo link if needed.

Please note that Github Provider are working fine where it generate session token.

Is this a bug in your own project?

Yes

How to reproduce ☕️

import NextAuth from 'next-auth';
import CredentialsProvider from 'next-auth/providers/credentials';
import GitHubProvider from 'next-auth/providers/github';
import { PrismaAdapter } from '@next-auth/prisma-adapter';
import { PrismaClient } from '@prisma/client';

import { verifyPassword, hashPassword } from '@functionHelpers/auth/passwords';

const prisma = new PrismaClient();

export default NextAuth({
	adapter: PrismaAdapter(prisma),
	secret: process.env.NEXTAUTH_SECRET,
	// session: {
	// 	jwt: true,
	// },
	pages: {
		// signIn: '/auth/signin',
		// signOut: "/auth/logout",
		// error: "/auth/error", // Error code passed in query string as ?error=
	},
	logger: {
		error(code, metadata) {
			console.log({ type: 'inside error logger', code, metadata });
		},
		warn(code) {
			console.log({ type: 'inside warn logger', code });
		},
		debug(code, metadata) {
			console.log({ type: 'inside debug logger', code, metadata });
		},
	},
	providers: [
		GitHubProvider({
			clientId: process.env.GITHUB_CLIENT_ID,
			clientSecret: process.env.GITHUB_CLIENT_SECRET,
		}),
		CredentialsProvider({
			id: 'app-login',
			name: 'App Login',
			credentials: {
				firstName: {
					label: 'First Name',
					type: 'text',
				},
				lastName: {
					label: 'last Name',
					type: 'text',
				},
				email: {
					label: 'Email Address',
					type: 'email',
				},
				password: {
					label: 'Password',
					type: 'password',
				},
			},
			async authorize(credentials, req) {
				console.log('Starting the signup/login process ---');
				try {
					let maybeUser = await prisma.user.findFirst({
						where: {
							email: credentials.email,
						},
					});

					// register process calling
					if (credentials.methodType === 'register') {
						if (!maybeUser) {
							if (
								!credentials.password ||
								!credentials.email ||
								!credentials?.firstName ||
								!credentials.lastName
							) {
								throw new Error('Please fill all of the information');
							}

							maybeUser = await prisma.user.create({
								data: {
									name: `${credentials.firstName} ${credentials.lastName}`,
									firstName: credentials.firstName,
									lastName: credentials.lastName,
									email: credentials.email,
									password: await hashPassword(credentials.password),
								},
							});
						} else {
							throw new Error('User already existed, please login.');
						}
					} else {
						// login process calling
						// user existed, need to verify user credentials

						if (!maybeUser) {
							throw new Error('No user found. Please create one');
						}

						if (!credentials.password || !credentials.email) {
							throw new Error('Please fill out all of the information');
						}

						const isValid = await verifyPassword(
							credentials?.password,
							maybeUser.password
						);
						if (!isValid) {
							throw new Error('Invalid Credentials');
						}
					}

					console.log('Ending the signup/login process ---');

					return maybeUser;
				} catch (error) {
					console.log(error);
					throw error;
				}
			},
		}),
	],
	callbacks: {
		async signIn({ user, account, profile, email, credentials }) {
			console.log('fire signin Callback');
			return true;
		},
		async redirect({ url, baseUrl }) {
			console.log('fire redirect Callback');
			return baseUrl;
		},
		async session({ session, user, token }) {
			console.log('fire SESSION Callback');
			return session;
		},
		async jwt({ token, user, account, profile, isNewUser }) {
			console.log('fire jwt Callback');

			// console.log({ token, user, account, profile, isNewUser });
			return token;
		},
	},
});

Screenshots / Logs 📽


Starting the signup/login process ---
Ending the signup/login process ---
fire signin Callback
fire jwt Callback
fire redirect Callback
{
  type: 'inside debug logger',
  code: 'adapter_getSessionAndUser',
  metadata: {
    args: [
      'eyJhbGciOiJkaXIiLCJlbmMiOiJBMjU2R0NNIn0..MLqO5WWIQ3nyCWSw.9EZyGxkX-5tWPQbfhDCcU_KzEvgt1EDKSEnC_px8RZ6q_Np8EfBYPIMVkBbgDkc7DdBRp3vssSAUWnNNoqjdvWlstqDQZ44roLQR-IUcYaWaOZQzH_Urau6gp6SluL9J2F69_eXnMSCtqT8h6sWzgtfaX4duZ1e6T49ryZr7qZmUHURYGK5Fxgnls4xHjtWEP7VZdZV_aLqIhAD5ZQ2HSmAjOWOgWUl8NoLhrWQoLSoD0g.TmT2wjs_7lhHifh2Er_kUg'   
    ]
  }
}
fire redirect Callback

Environment 🖥

Windows 11

Contributing 🙌🏽

Yes, I am willing to help solve this bug in a PR

Issue Analytics

  • State:open
  • Created 2 years ago
  • Reactions:8
  • Comments:11 (1 by maintainers)

github_iconTop GitHub Comments

19reactions
leosuncincommented, Apr 6, 2022

I had the same problem but with mongodb adapter, and the problem was I didn’t pay attention to

So, the missing piece is set the session’s strategy to jwt, as follow:

import { MongoDBAdapter } from '@next-auth/mongodb-adapter';
import { verify } from '@node-rs/bcrypt';
import NextAuth, { type User } from 'next-auth';
import CredentialsProvider from 'next-auth/providers/credentials';
import EmailProvider from 'next-auth/providers/email';

import clientPromise from '../../../lib/mongodb';

declare module 'next-auth' {
  interface User {
    password?: string;
  }
}

export default NextAuth({
  adapter: MongoDBAdapter(clientPromise),
  // Configure one or more authentication providers
  providers: [
    EmailProvider({
      name: 'Magic link',
      secret: process.env.NEXTAUTH_SECRET,
      from: process.env.EMAIL_FROM,
      server: process.env.EMAIL_SERVER ?? {
        host: 'localhost',
        port: 1025,
        secure: false,
        ignoreTLS: true,
      },
    }),
    CredentialsProvider({
      name: 'Account',
      credentials: {
        email: {
          label: 'Email',
          type: 'email',
          placeholder: 'Enter your email',
        },
        password: {
          label: 'Password',
          type: 'password',
          placeholder: 'Enter password',
        },
      },
      async authorize(credentials) {
        if (!credentials) return null;

        const client = await getMongoClient();
        const users = client.db().collection<User>('users');
        const user = await users.findOne({ email: credentials.email });

        if (!user) return null;

        if (
          typeof user.password === 'string' &&
          !(await verify(credentials.password, user.password))
        ) {
          return null;
        } else {
          delete user.password;
        }

        return user;
      },
    }),
    // ...add more providers here
  ],
  debug: process.env.NODE_ENV === 'development',
  session: {
    // Set to jwt in order to CredentialsProvider works properly
    strategy: 'jwt'
  }
});

Edit:
Link to the docs https://next-auth.js.org/configuration/providers/credentials

6reactions
larsnietcommented, Feb 22, 2022
  session: {
    // Set to jwt in order to CredentialsProvider works properly
    strategy: 'jwt'
  }

You are AMAZING! I have been scratching my head for a week and yet, it’s so simple… Thanks so much man!

Read more comments on GitHub >

github_iconTop Results From Across the Web

Next Auth Credentials Provider JWT / Session callback
import CredentialsProvider from "next-auth/providers/credentials"; ... jwt callback is only called when token is created async jwt({ token, ...
Read more >
Errors - NextAuth.js
If you are using a Credentials Provider, NextAuth.js will not persist users or sessions in a database - user accounts used with the ......
Read more >
Implementing Credentials Provider on NextJS and NextAuth ...
How to implement the credentials provider using NextJS and NextAuth using custom sign in form and MySQL database (with Prisma)
Read more >
Authenticating with your backend using NextAuth.js
In this article, we will use the Credentials provider. Callbacks. Callbacks are asynchronous functions useful for hooking into specific parts of ...
Read more >
How to implement NextAuth using credentials provider with ...
It calls /api/auth/session and returns a promise with a session object, or null if no session exists. Client Side Example. async function ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found