JWT は、Json Web Token の略です。

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

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

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

index.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

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

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

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を設定します。

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

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

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;
      }
    })
};

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

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)
  })
}

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

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 を呼び出します。

const jwt = require("jsonwebtoken")

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

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 の第二引数に、秘密鍵を設定します。

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

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 時間にします。

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 とトークンを返す様にします。

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 })
    })
}

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

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

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

ブログ一覧