User object is empty #2762
-
Question 💬Hi, I use 4.0.0-beta.2 version, credentials login, MongoDB for storing users and JWT. The problem is that, right now, I can log in without a problem, log out, but the session object contains an empty user object - so I can't render users username and so on. Did someone have a similar problem? My previous apps that ran v3 worked flawlessly. I inserted a few code snippets below, that should explain my code a little bit Thanks in advance 🙂 How to reproduce ☕️Session object {
"user": {},
"expires": "2021-10-14T22:04:10.401Z"
} Page dashboard.jsx import { useSession } from "next-auth/react";
const Dashboard = () => {
const { data: session, status } = useSession();
const logSession = () => {
console.log(session, status);
};
};
export default Dashboard; [..nextauth.js] import NextAuth from "next-auth";
import CredentialsProvider from "next-auth/providers/credentials";
export default NextAuth({
pages: {
signIn: "/auth/login",
signOut: "/auth/logout",
error: "/auth/error",
verifyRequest: "/auth/verify-request",
},
debug: true,
providers: [
CredentialsProvider({
async authorize(credentials) {
const res = await fetch("http://localhost:3000/api/auth/login", {
method: "POST",
body: JSON.stringify(credentials),
headers: { "Content-Type": "application/json" },
});
const user = await res.json();
if (res.ok && user) {
console.log(user);
// {
// _id: '612b4646c41e9e9f5068727a',
// password: 'Test123456789',
// username: 'admin'
// }
return user;
} else {
return null;
}
},
}),
],
session: {
jwt: true,
maxAge: 30 * 24 * 60 * 60,
},
jwt: {
signingKey: process.env.JWT_SIGNING_PRIVATE_KEY,
},
}); _app.jsx import "../index.css";
import "@fortawesome/fontawesome-svg-core/styles.css";
import { appWithTranslation } from "next-i18next";
import { BoxedLayout } from "components/layouts/Boxed/Layout";
import { AdminLayout } from "components/layouts/Admin/Layout";
import { SessionProvider } from "next-auth/react";
import Auth from "components/Auth";
const layouts = {
L1: BoxedLayout,
L3: AdminLayout,
};
const MyApp = ({ Component, pageProps: { session, ...pageProps } }) => {
const Layout = layouts[Component.layout] || ((children) => <>{children}</>);
return (
<SessionProvider session={session}>
{Component.auth ? (
<Auth>
<Layout>
<Component {...pageProps} />
</Layout>
</Auth>
) : (
<Layout>
<Component {...pageProps} />
</Layout>
)}
</SessionProvider>
);
};
export default appWithTranslation(MyApp); Contributing 🙌🏽Yes, I am willing to help answer this question in a PR |
Beta Was this translation helpful? Give feedback.
Replies: 6 comments 12 replies
-
you mention mongodb, but we intentionally don't support databases with the credentials provider, so I assume it's something custom? not necessarily the issue, but in your authorize callback, you should rather import the logic to Could you provide a runnable reproduction so I could test it out? I also don't understand when do you get the empty user object? After login, logout or both? |
Beta Was this translation helpful? Give feedback.
-
I've experienced same issue with v4-beta2 (reported here https://github.com/nextauthjs/adapters/issues/219#issuecomment-919016150) and here same issue was reported as well: #2746 - don't get why his issue was closed but anyway. |
Beta Was this translation helpful? Give feedback.
-
@AydinChavez your issues seem to be unrelated, I am still waiting for a proper reproduction for https://github.com/nextauthjs/adapters/issues/219#issuecomment-919016150 that I can have a look at on my computer. #2746 didn't have a reproduction and wasn't closed per se, but converted to a discussion since it was labeled as a question, which we have a note about in the question issue form when filling out: (It's actually this issue that I just forgot to convert yet) Remember that without a reproduction, it is not easier for us to debug a problem than for anyone else. 🤷 Regarding testing: We have already introduced client-side tests: #1992 #2295 and we are in the works of testing as many providers as we possibly can, see #2524, but we rely on our community here, as we have a high number of things to support due to being flexible, as you say. ALL merged Adapters are going through the same test suite introduced in nextauthjs/adapters#171 The core has recently been refactored to TypeScript to catch a bunch of things build-time #2552. I would say we have come a long way in terms of testing, in comparison v3 had no tests whatsoever. If you have any suggestions or would like to contribute to improving testing, we welcome any help! 🙏 Regarding the state of the beta release: We could argue about terms of alpha, beta, or experimental, but at the end of the day, when installing a To make this more constructive, you can help advance things the most if you provide as much info as possible from the get-go, and help out others who have problems (remember we have to answer everyone's questions at the same time, and not everyone has a related issue to yours). The general feedback to v4 has been mixed, but I also got feedback that said migrating was a breeze. 🤷 |
Beta Was this translation helpful? Give feedback.
-
I figured it out, and it's completely my mistake, the problem actually lies in my mind. I thought that when we return a user object, it doesn't matter which properties the object has. But it does! Because this: async authorize(credentials) {
const user = {
_id: "612b4646c41e9e9f5068727a",
password: "Test123456789",
username: "admin",
};
return user;
}, makes the user object inside session empty: {
"user": {},
"expires": "2021-10-15T11:28:24.085Z"
} But, when we use the predefined names of properties: async authorize(credentials) {
const user = {
_id: "612b4646c41e9e9f5068727a",
email: "[email protected]",
name: "admin",
};
return user;
}, we now have the user object with properties name and email and their respective values: {
"user": {
"name": "admin",
"email": "[email protected]"
},
"expires": "2021-10-15T11:37:47.982Z"
} The right waySo, if I want to use the data I get from my API route, I need to use callbacks like this: providers: [
CredentialsProvider({
async authorize(credentials) {
const res = await fetch("http://localhost:3000/api/auth/login", {
method: "POST",
body: JSON.stringify(credentials),
headers: { "Content-Type": "application/json" },
});
const user = await res.json();
if (res.ok && user) {
return user;
} else {
return null;
}
},
}),
],
session: {
jwt: true,
maxAge: 30 * 24 * 60 * 60,
},
jwt: {
signingKey: process.env.JWT_SIGNING_PRIVATE_KEY,
},
callbacks: {
async session({ session, token }) {
session.user = token.user;
return session;
},
async jwt({ token, user }) {
if (user) {
token.user = user;
}
return token;
},
}, which then correctly sets my user object as I want: {
"user": {
"_id": "612b4646c41e9e9f5068727a",
"password": "Test123456789",
"username": "admin"
},
"expires": "2021-10-15T11:41:29.324Z"
} V3 > V4The little difference between V3 and V4 in the first example above is, that while V3 would set the user object inside the session like this: {
"user": {
"name": null,
"email": null,
"image": null
},
"expires": "2021-10-15T11:37:47.982Z"
} V4 sets it (as I already wrote above) this way: {
"user": {},
"expires": "2021-10-15T11:28:24.085Z"
} which may have confused my head, but it's more probable that I'm just dumb and forgot. @balazsorban44 By the way, keep up the good work, I love this project, and it helped me in several web apps, V4 works fine for me, this has been the first time I had any problem with it, and if I didn't forgot, I wouldn't even have one. 🙂 |
Beta Was this translation helpful? Give feedback.
-
Thank you so much @choutkamartin for the solution. |
Beta Was this translation helpful? Give feedback.
-
Thanks for the solution! If someone needs TS support also: declare module 'next-auth' {
interface Session extends DefaultSession {
user: SafeUserType; // your user type
}
interface User extends SafeUserType {}
}
declare module 'next-auth/jwt' {
interface JWT {
user: SafeUserType;
}
} ..and to have typed authorize parameters in CredentialsProvider credentials config option also needed (using empty objects for pw/username, assuming a custom sign in page) ...
credentials: {
password: {},
username: {},
},
... |
Beta Was this translation helpful? Give feedback.
I figured it out, and it's completely my mistake, the problem actually lies in my mind. I thought that when we return a user object, it doesn't matter which properties the object has. But it does! Because this:
makes the user object inside session empty:
But, when we use the predefined names of properties: