【Node.js】jsonwebtokenを使って、JWTを設定する
Node.js

【Node.js】jsonwebtokenを使って、JWTを設定する

作成日:2021年11月10日
更新日:2021年11月10日

JWT は、Json Web Token の略です。

JWT を使用することで、JSON オブジェクトの認証データを安全に送信することができます。

node.js で JWT を使用するために、jsonwebtoken を追加します。

コードは、前回までのコードを使用します。

nodejs-bcrypt

【Node.js】bcryptを使って、パスワードをハッシュに変換する

index.js

js
const express = require("express");
const bodyParser = require("body-parser");
const mongoose = require("mongoose");
const authRoutes = require("./routes/auth");
const app = express();
app.use(bodyParser.json());
app.use((req, res, next) => {
res.setHeader("Access-Control-Allow-Origin", "*");
res.setHeader(
"Access-Control-Allow-Methods",
"GET, POST, PUT, PATCH, DELETE, OPTION"
);
res.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization");
next();
});
app.use("/auth", authRoutes);
mongoose
.connect(
"mongodb+srv://Nao:abcdefgh.q1atv.mongodb.net/myFirstDatabase?retryWrites=true&w=majority"
)
.then(() => {
app.listen(8000);
console.log("Server is running ...");
})
.catch((err) => {
console.log(err);
throw err;
});

routes/auth.js

js
const express = require("express");
const { body } = require("express-validator");
const authController = require("../controllers/auth");
const router = express.Router();
router.post(
"/sign_up",
[
body("email")
.isEmail()
.withMessage("メールアドレスを入力してください")
.normalizeEmail(),
body("password").trim().isLength({ min: 4 }),
],
authController.signUp
);
module.exports = router;

model/user.js

js
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const userShema = new Schema({
email: String,
password: String,
});
module.exports = mongoose.model("User", userShema);

controllers/auth.js

js
const User = require("../model/user");
const { validationResult } = require("express-validator");
const bcrypt = require("bcrypt");
exports.signUp = (req, res, next) => {
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res
.status(400)
.json({ message: "validation errors", errors: errors.array() });
}
const email = req.body.email;
const password = req.body.password;
bcrypt
.hash(password, 10)
.then((hashedPassword) => {
const user = new User({
email: email,
password: hashedPassword,
});
return user.save();
})
.then(() => {
res.status(201).json({
message: "User transmission completed!",
});
})
.catch((err) => console.log(err));
};

ターミナルで、npm install --save jsonwebtokenを実行します。

controllers の auth.js を開きます。

loginを作成し、emailpasswordを設定します。

js
exports.login = (req, res, next) => {
const email = req.body.email;
const password = req.body.password;
};

mongoose の findOne で、emailを選択します。

js
exports.login = (req, res, next) => {
const email = req.body.email;
const password = req.body.password;
User.findOne({ email: email });
};

もし、メールアドレスが見つからなかった場合、エラーを出力する様にします。

js
.then((result) => {
if (!result) {
const error = new Error("メールアドレスが存在しません");
error.statusCode = 401;
throw error;
}
})
};

bcrypt でハッシュ化したパスワードと入力したパスワードがあっているか検証します。

js
exports.login = (req, res, next) => {
const email = req.body.email;
const password = req.body.password;
User.findOne({ email: email }).then((result) => {
if (!result) {
const error = new Error("メールアドレスが存在しません");
error.statusCode = 401;
throw error;
}
return bcrypt.compare(password, result.password);
});
};

次に、パスワードが間違っている場合は、エラーを出力します。

js
exports.login = (req, res, next) => {
const email = req.body.email;
const password = req.body.password;
User.findOne({ email: email })
.then((result) => {
if (!result) {
const error = new Error("メールアドレスが存在しません");
error.statusCode = 401;
throw error;
}
return bcrypt.compare(password, result.password);
})
.then((result) => {
if (!result) {
const error = new Error("パスワードが間違っています");
error.statusCode = 401;
throw error;
}
};

jsonwebtoken を呼び出します。

js
const jwt = require("jsonwebtoken");

jsonwebtoken の sign に、email を保存します。

js
exports.login = (req, res, next) => {
const email = req.body.email;
const password = req.body.password;
User.findOne({ email: email })
.then((result) => {
if (!result) {
const error = new Error("メールアドレスが存在しません");
error.statusCode = 401;
throw error;
}
return bcrypt.compare(password, result.password);
})
.then((result) => {
if (!result) {
const error = new Error("パスワードが間違っています");
error.statusCode = 401;
throw error;
}
const token = jwt.sign({
email: email,
});
});
};

sign の第二引数に、秘密鍵を設定します。

今回は、適当な文字列にします。

js
exports.login = (req, res, next) => {
const email = req.body.email;
const password = req.body.password;
User.findOne({ email: email })
.then((result) => {
if (!result) {
const error = new Error("メールアドレスが存在しません");
error.statusCode = 401;
throw error;
}
return bcrypt.compare(password, result.password);
})
.then((result) => {
if (!result) {
const error = new Error("パスワードが間違っています");
error.statusCode = 401;
throw error;
}
const token = jwt.sign(
{
email: email,
},
"abcabcabcabcd"
);
});
};

第三引数に、トークンの有効期限を設定します。

今回は、1 時間にします。

js
exports.login = (req, res, next) => {
const email = req.body.email;
const password = req.body.password;
User.findOne({ email: email })
.then((result) => {
if (!result) {
const error = new Error("メールアドレスが存在しません");
error.statusCode = 401;
throw error;
}
return bcrypt.compare(password, result.password);
})
.then((result) => {
if (!result) {
const error = new Error("パスワードが間違っています");
error.statusCode = 401;
throw error;
}
const token = jwt.sign(
{
email: email,
},
"abcabcabcabcd",
{ expiresIn: "1h" }
);
});
};

ログインが成功した場合、ステータスコード 200 とトークンを返す様にします。

js
exports.login = (req, res, next) => {
const email = req.body.email;
const password = req.body.password;
User.findOne({ email: email })
.then((result) => {
if (!result) {
const error = new Error("メールアドレスが存在しません");
error.statusCode = 401;
throw error;
}
return bcrypt.compare(password, result.password);
})
.then((result) => {
if (!result) {
const error = new Error("パスワードが間違っています");
error.statusCode = 401;
throw error;
}
const token = jwt.sign(
{
email: email,
},
"abcabcabcabcd",
{ expiresIn: "1h" }
);
return res.status(200).json({ token: token });
});
};

エラーの場合、エラーメッセージを表示します。

js
exports.login = (req, res, next) => {
const email = req.body.email;
const password = req.body.password;
User.findOne({ email: email })
.then((result) => {
if (!result) {
const error = new Error("メールアドレスが存在しません");
error.statusCode = 401;
throw error;
}
return bcrypt.compare(password, result.password);
})
.then((result) => {
if (!result) {
const error = new Error("パスワードが間違っています");
error.statusCode = 401;
throw error;
}
const token = jwt.sign(
{
email: email,
},
"abcabcabcabcd",
{ expiresIn: "1h" }
);
return res.status(200).json({ token: token });
})
.catch((err) => console.log(err));
};

一通り完成したので、Postman で確認します。

image2

image3

では、送信ボタンを押してみます。

image4

無事、トークンが返ってきました。

© 2024あずきぱんウェブスタジオ