
Using an ID/Password + JWT
Next.js version
"next": "13.2.4”
Setting up the library
npm install bcrypt
If you want to log in using the username/password method
You can do this by selecting the Credentials provider in the Next-auth
library settings.
However, in this case, we are forced to use the JWT method instead of the session method.
Let’s start by creating a signup page and functionality.
- On the signup page, when the user submits their username/password to the server, the
- The server stores it in the DB
Let’s implement it as is.
1. When the user submits their username/password on the signup page, the
(app/register/page.js)
export default function Register() {
return (
<div>
<form method="POST" action="/api/auth/signup">
<input name="name" type="text" placeholder="Name" />
<input name="email" type="text" placeholder="E-mail" />
<input name="password" type="password" placeholder="PW" />
<button type="submit">Request</button>
</form>
</div>
);
}
The reason I left out id
and only put email is because I wanted to use the
When I log in with OAuth
, I don’t see a username, only an email.
Writing emails also serves a sort of consistency purpose.
2. The server stores it in the DB
We want to store the password encrypted in the DB, so we install the encryption library bcrypt.
(pages/api/auth/signup.js)
import bcrypt from "bcrypt";
import { connectDB } from "util/database";
export default async function handler(req, res) {
if (req.method === "POST") {
let { name, email, password } = req.body;
if (!name || !email || !password) {
return res.status(400).json("Spaces are not allowed.");
}
let db = (await connectDB).db("forum");
const compareDB = await db
.collection("user_cred")
.findOne({ email: email });
if (compareDB) {
return res.status(400).json("An account that already exists.");
}
const hash = await bcrypt.hash(password, 10);
password = hash;
await db.collection("user_cred").insertOne({
name,
email,
password,
role: "user",
});
res.status(200).json("Sucess!");
} else {
res.status(400).json("This is an incorrect approach.");
}
}
(1) Put your password in bcrypt.hash
and it will encrypt it. 10 is the encryption level, but you can modify it as you like
(2) Then I told it to create the user information as an object and put it in the user_cred collection.
Set up a credentials provider
If you also set the Credentials provider in the Next-auth
setting, you can log in with your username/password.
import NextAuth from "next-auth";
import GithubProvider from "next-auth/providers/github";
import { MongoDBAdapter } from "@next-auth/mongodb-adapter";
import { connectDB } from "util/database";
import CredentialsProvider from "next-auth/providers/credentials";
import bcrypt from "bcrypt";
export const authOptions = {
providers: [
GithubProvider({
clientId: process.env.CLIENT_ID,
clientSecret: process.env.CLIENT_PW,
}),
CredentialsProvider({
//1. Code to automatically generate a login page form
name: "credentials",
credentials: {
email: { label: "email", type: "text" },
password: { label: "password", type: "password" },
},
//2. Code executed on login request
//Compare IDs and passwords directly from the DB and use the
//Should return result if id and password are correct, return null if incorrect
async authorize(credentials) {
let db = (await connectDB).db("forum");
let user = await db
.collection("user_cred")
.findOne({ email: credentials.email });
if (!user) {
console.log("No such emails");
return null;
}
const pwcheck = await bcrypt.compare(
credentials.password,
user.password
);
if (!pwcheck) {
console.log("Wrong pw");
return null;
}
return user;
},
}),
],
//3. Write a JWT to make it work + Set a JWT expiration date
session: {
strategy: "jwt",
maxAge: 30 * 24 * 60 * 60, //30day
},
callbacks: {
//4. Code executed when creating a JWT
//The user variable contains the user information of the DB, and if you store something in token.user, it will be entered into the jwt.
jwt: async ({ token, user }) => {
if (user) {
token.user = {};
token.user.name = user.name;
token.user.email = user.email;
token.user.role = user.role;
}
return token;
},
//5. Code that runs every time a user session is looked up
session: async ({ session, token }) => {
session.user = token.user;
return session;
},
},
secret: process.env.JWT_SECRET,
adapter: MongoDBAdapter(connectDB),
};
export default NextAuth(authOptions);
You don’t need to memorize and study the library usage, you can just copy and paste it.
The most important thing is number 2.
You need to compare the login ID/password with the contents stored in the DB.
Let’s modify it to suit your DB situation.