Open Suonx002 opened 2 years ago
I have the same issue, GitHub settings works correctly fires session callback but not with Credentials settings, here are my settings:
import NextAuth from "next-auth";
import GitHubProvider from "next-auth/providers/github"
import CredentialsProvider from "next-auth/providers/credentials";
import { PrismaAdapter } from "@next-auth/prisma-adapter"
import prisma from '../../../lib/prisma'
export default NextAuth({
adapter: PrismaAdapter(prisma),
providers: [
GitHubProvider({
clientId: process.env.GITHUB_ID,
clientSecret: process.env.GITHUB_SECRET
}),
CredentialsProvider({
id: 'app-login',
name: "Credentials",
credentials: {
username: { label: "Username", type: "text", placeholder: "Insert username" },
password: { label: "Password", type: "password", placeholder: "Insert password"}
},
async authorize(credentials, req) {
// Add logic here to look up the user from the credentials supplied
const user = { id: 1, name: 'Admin' };
if (user) {
return user
} else {
return null
}
}
})
],
secret: process.env.SECRET,
session: {
},
jwt: {},
pages: {},
callbacks: {
async signIn(req) {
return true
},
// async redirect(url, baseUrl) { return baseUrl },
async session(req) {
return req.session
},
// async jwt(token, user, account, profile, isNewUser) { return token }
},
events: {},
theme: {
colorScheme: "light", // "auto" | "dark" | "light"
brandColor: "", // Hex color code
logo: "" // Absolute URL to image
},
debug: true,
})
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
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' } });
This is awesome, thank you for your help!
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!
session: {
// Set to jwt in order to CredentialsProvider works properly
strategy: 'jwt'
}
Thank you so much it works perfectly!!!
@leosuncin where did you see that notice? I'm not seeing that on the current documentation
Here https://next-auth.js.org/configuration/providers/credentials @pianomansam
@leosuncin perhaps we should display it in both places, then, because I only knew about the documentation page I linked to
Weirdly this issue didn't affect me until I started using multiple providers - when I only had credential provider it worked without any issues. Definitely not obvious in the current docs.
session: { // Set to jwt in order to CredentialsProvider works properly strategy: 'jwt' }
Thanks a lot!!
You can also use the 'database' strategy with this work-around. https://github.com/nextauthjs/next-auth/discussions/4394#discussioncomment-3293618
I had a way to use jwt strategy to work with session by default in latest next-auth
https://github.com/nextauthjs/next-auth/discussions/4394#discussioncomment-3293618
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
Send by God !
Why it's no the default config ?
@ElvisDev187 this is from the documentation
Choose how you want to save the user session. The default is "jwt", an encrypted JWT (JWE) in the session cookie.
If you use an adapter however, we default it to "database" instead. You can still force a JWT session by explicitly defining "jwt".
When using "database", the session cookie will only contain a sessionToken value, which is used to look up the session in the database.
Ok now it's fine for me
Le mer. 17 mai 2023 à 23:35, Mário Santos @.***> a écrit :
@ElvisDev187 https://github.com/ElvisDev187 this is from the documentation
Choose how you want to save the user session. The default is "jwt", an encrypted JWT (JWE) in the session cookie.
If you use an adapter however, we default it to "database" instead. You can still force a JWT session by explicitly defining "jwt".
When using "database", the session cookie will only contain a sessionToken value, which is used to look up the session in the database.
— Reply to this email directly, view it on GitHub https://github.com/nextauthjs/next-auth/issues/3970#issuecomment-1552171983, or unsubscribe https://github.com/notifications/unsubscribe-auth/AUBZVKPZTHN3W3SADBSWOGLXGVHBLANCNFSM5OJ4SMSA . You are receiving this because you were mentioned.Message ID: @.***>
@mariosantosdev thx, I understand better now, I was a bit confused at first.
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!
I had the same problem. I use TiDB and GoogleProvider.
I add relationMode = "prisma"
. It works!
schema.prisma
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "mysql"
url = env("DATABASE_URL")
+ relationMode = "prisma"
}
Hi everyone. I searched online and read through all posts in this thread, but I cannot seem to get my set up to fire the "session" callback. I was extremely excited to see that I missed the "session: { strategy: 'jwt' }" as other did, but, alas, after adding it to my NextAuth options, the "session" callback is still not firing.
I have trimmed down everything to make sure only "good" data is getting sent through the system, creating a simple hard-coded user to return from the "authorize" function. After signing in, "authorize" runs as it should, the "jwt" callback is fired, but I never see the console log printed out in the "session" callback. Any help you all could provide would be much appreciated.
I'm simply using the default "Sign In" and "Log Out" pages and just the "Credentials Provider" with no adapter. Here's my code for the "/api/auth/[...nextauth]/route.ts" file:
import NextAuth from "next-auth"
import CredentialsProvider from "next-auth/providers/credentials"
export const authOptions: NextAuthOptions = {
providers: [
CredentialsProvider({
name: "mSecure Credentials",
credentials: {
username: {
label: "Username",
type: "text",
placeholder: "username"
},
password: {
label: "Password",
type: "password",
placeholder: "enter password"
}
},
async authorize(credentials) {
const user = {
id: "1000",
email: "mike@msecure.com",
name: "Mike Reilley"
}
if (user) {
return user
}
return null
}
})
],
callbacks: {
async jwt({ token, user, session }) {
console.log("jwt callback fired")
return token
},
async session({ session, token, user }) {
console.log("session callback fired")
return session
}
},
debug: process.env.NODE_ENV === "development",
session: {
strategy: "jwt",
// Seconds - How long until an idle session expires and is no longer valid.
maxAge: 30 * 24 * 60 * 60 // 30 days
}
}
const handler = NextAuth(authOptions)
export { handler as GET, handler as POST }
@deelydian - at a glance the only obvious difference between what you have here and what I got working is the lack of secret: process.env.NEXT_AUTH_SECRET
within options - not a required in NODE_ENV === 'development'
but is required in NODE_ENV === 'production'
.
Haven't checked but I'd expect session callback is only called when you call useSession
in a page.
Thank you for the response @OffBy0x01. I do have the process.env.NEXT_AUTH_SECRET, so that definitely wasn't the problem. So far as I can tell, everything is actually working. I was confused because everything I read and watched was showing the "session" callback getting called every time an update was made to the code in VS Code and the browser page was refreshed either manually or through live updating. That had to be because there was a "useSession" call being made, but I just didn't see it.
At any rate, I can confirm everything is working correctly. I'm able to use "useSession" in client components and "getToken" in server components to get the information I need to authenticate with my Parse backend. Thank you again for your response.
Did you find any solution. I'm currently in a similar situation. I have the NEXT_AUTH_SECRET set up. I also did hardcode a user but it turns out when i try to sign in it doesn't fire the authenticate. I get redirected to
http://localhost:3000/api/auth/error.
and my browser console logs:
GET http://localhost:3000/api/auth/providers 404 (Not Found)
[next-auth][error][CLIENT_FETCH_ERROR]
https://next-auth.js.org/errors#client_fetch_error Unexpected token '<', "<!DOCTYPE "... is not valid JSON {error: {…}, url: '/api/auth/providers', message: Unexpected token '<', "<!DOCTYPE "... is not valid JSON
}
Current on; "next": "^14.0.3", "next-auth": "^4.24.5",
here i how my code looks currently
src\app\api\auth\[...nextauth]\route.ts
import {
getServerSession, type NextAuthOptions,
} from "next-auth";
import Credentials from "next-auth/providers/credentials";
import { authService } from "./userAuthentication";
export const authOptions: NextAuthOptions = {
secret: process.env.NEXTAUTH_SECRET,
debug: process.env.NODE_ENV === "development",
session: {
strategy: "jwt",
},
pages: {
signIn: '/user/login',
error: '/user/login',
},
providers: [
Credentials({
name: "Credentials",
type: "credentials",
credentials: {
username: { label: "Username", type: "text" },
password: { label: "Password", type: "password" }
},
async authorize(credentials) {
console.log("credentials reached");
const { username, password } = credentials as {
username: string
password: string
};
try {
const user = await authService.authenticate(username, password);
if (user) return user;
} catch (error) {
console.log(error)
}
}
})
],
callbacks: {
async jwt({ token, account, profile }) {
if (account && account.type === "credentials") {
token.userId = account.providerAccountId;
}
return token;
},
async session({ session, token, user }) {
session.user.id = token.userId;
return session;
},
async redirect({ url, baseUrl }) {
return "/";
},
},
};
const handler = NextAuth(authOptions);
export { handler as GET, handler as POST };
../../userAuthenticate.ts
function authenticate(username: string, password: string) {
const user = {
id: "3",
name: "Test User",
email: "testuser@example.com"
};
return Promise.resolve(user);
}
export const authService = {
authenticate,
};
@SakoeCourage We're having this issue with the signIn()
function of next-auth/react
as well. Logging in works, but I have to do something like signIn().catch(router.refresh)
.
@balazsorban44 We (https://github.com/teamhanko) are building a NextAuth provider for our open-source passkeys API, so .catch
ing everything wouldn't be feasible :\
We have to call signIn()
from our lib because we need to pass things into it that have to be computed on the client. We can't easily get access to the signIn()
function exported from auth.ts of the user, which I'm guessing would solve this issue too instead of using next-auth/react
— is there a recommended way of doing this?
Do you know if this issue is related to the original post or if it's a separate thing? For what it's worth, I initially landed here because I searched for why signIn()
didn't refresh my current route/work until I refreshed the page, hah
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 ☕️
Screenshots / Logs 📽
Environment 🖥
Windows 11
Contributing 🙌🏽
Yes, I am willing to help solve this bug in a PR