Next auth with MongoDB
Unanswered
Channel catfish posted this in #help-forum
Channel catfishOP
How to handle PUT actions (name updating in my case) with Next Auth and MongoDB?
9 Replies
Capelin
What exactly are you trying to do?
@Capelin What exactly are you trying to do?
Channel catfishOP
I'm trying to update the name (of a user whose credentials are cached in Next Auth and user information in MongoDB) in a client-side component, but I'm not quite sure what to do in [...nextauth], also not sure if there's need to create a front end API component for updating the name (ex. api/updateName).
Capelin
So you use Credentials to store user information like username and hashed password inside mongoDb, then you want to manipulate the session JWT object AND the mongoDb at the same time?
Channel catfishOP
So you use Credentials to store user information like username and hashed password inside mongoDb - nope, they're in next auth:
CredentialsProvider({
name: "credentials",
credentials: {},
async authorize(credentials) {
const { email, password } = credentials;
try {
await connectMongoDB();
const user = await User.findOne({ email });
if (!user) {
return null;
}
const passwordsMatch = await bcrypt.compare(password, user.password)
if(!passwordsMatch){
return null;
}
return user;
-when user creates an account, name,email and pw are stored in MongoDB, and also stored in credentials (next auth), for example, it looks like this to show logged user's name and email:
Email: <span className="font-bold">{session?.user?.email}</span>
CredentialsProvider({
name: "credentials",
credentials: {},
async authorize(credentials) {
const { email, password } = credentials;
try {
await connectMongoDB();
const user = await User.findOne({ email });
if (!user) {
return null;
}
const passwordsMatch = await bcrypt.compare(password, user.password)
if(!passwordsMatch){
return null;
}
return user;
-when user creates an account, name,email and pw are stored in MongoDB, and also stored in credentials (next auth), for example, it looks like this to show logged user's name and email:
Email: <span className="font-bold">{session?.user?.email}</span>
Capelin
Does this look for a user inside mongoDb?
const user = await User.findOne({ email });
const user = await User.findOne({ email });
Channel catfishOP
Yes, it finds email, stored in the database, because when a user has to log in, they have to write email and pw
Capelin
Right, so you do use mongoDb to store user information.
Regardless, the JWT callback is triggered whenever the JWT object - which you access with session?.user?.email, is updated.
https://next-auth.js.org/configuration/callbacks
Regardless, the JWT callback is triggered whenever the JWT object - which you access with session?.user?.email, is updated.
https://next-auth.js.org/configuration/callbacks
Channel catfishOP
Should I make a separate Frontend api form (like I did when I made RegisterForm for creating a new user) to handle name change?
Register form snippet:
const { name, email, password } = await req.json();
const hashedPassword = await bcrypt.hash(password, 10);
await connectMongoDB();
await User.create({ name, email, password: hashedPassword });
Register form snippet:
const { name, email, password } = await req.json();
const hashedPassword = await bcrypt.hash(password, 10);
await connectMongoDB();
await User.create({ name, email, password: hashedPassword });
Capelin
Not sure what the best solution is, I'm looking at this myself at the moment too.
Ideally you want to handle all user creation/authentication on the backend.
You definitely do not want to expose any secrets used for encryption on the frontend.
However, next-auth is (in my opinion) really bad at handling credential sign-in.
Although very convenient in terms of handling csrf tokens. Which you must handle yourself if you're not using "
await signIn("credentials", {
username: username,
password: password,
redirect: false,
}
" on the frontend to send the login information to next-auth.
You would have to store the data inside MongoDb somehow. So the question is whether to do this from the frontend, or from the backend.
The options as far as I see it is between simply updating the session object, then syncing the mongoDb with the session inside the JWT callback.
Or using the MongoDB for all user data, and simply ignore the session object. But you would probably create a session provider anyway later down the line to store user information between pages.
If you store it in mongoDb via the frontend, you'd obviously also need to add some form of authentication to make sure that it's in fact the currently logged in user that is trying to update the database.
If you update the database from inside the JWT callback, the user would already be authenticated. But, you would have to map over the session.user object and compare to the database if a value has changed. (I assume).
If you are lucky, the JWT callback may have a way to check what data in the session object has changed. And if that is the case, you can simply update the MongoDb database when the callback is triggered.
Ideally you want to handle all user creation/authentication on the backend.
You definitely do not want to expose any secrets used for encryption on the frontend.
However, next-auth is (in my opinion) really bad at handling credential sign-in.
Although very convenient in terms of handling csrf tokens. Which you must handle yourself if you're not using "
await signIn("credentials", {
username: username,
password: password,
redirect: false,
}
" on the frontend to send the login information to next-auth.
You would have to store the data inside MongoDb somehow. So the question is whether to do this from the frontend, or from the backend.
The options as far as I see it is between simply updating the session object, then syncing the mongoDb with the session inside the JWT callback.
Or using the MongoDB for all user data, and simply ignore the session object. But you would probably create a session provider anyway later down the line to store user information between pages.
If you store it in mongoDb via the frontend, you'd obviously also need to add some form of authentication to make sure that it's in fact the currently logged in user that is trying to update the database.
If you update the database from inside the JWT callback, the user would already be authenticated. But, you would have to map over the session.user object and compare to the database if a value has changed. (I assume).
If you are lucky, the JWT callback may have a way to check what data in the session object has changed. And if that is the case, you can simply update the MongoDb database when the callback is triggered.