Hari 13: Authentication Express

30 Hari Javascript

Subscribe to my newsletter and never miss my upcoming articles

Senangnya kita telah menyelesaikan CRUD pada database, sekarang yang kita inginkan adalah data yang aman, yang berhak yang boleh mengubah atau menghapus data tersebut.

Authentication

Pada tabel user kita telah memiliki beberapa kolom yaitu id, name, label, picture, email, phone, website, summary tetapi untuk melakukan login kita butuh setidaknya email dan password, karena itu kita akan menambahkan kolom password.

Tambah Kolom Sequelize

Untuk menambahkan kolom pada sequelize, lakukan peintah berikut.

sequelize migration:create --name add_column_password

Sehingga menghasilkan file migrasi, seperti gambar berikut.

https://raw.githubusercontent.com/AsrulLove/img-db/master/migrasi-column.png

Ubah isi file migrasi tersebut sehingga menjadi seperti berikut.

"use strict";

module.exports = {
  up: (queryInterface, Sequelize) => {
    return queryInterface.addColumn("Users", "password", Sequelize.STRING);
  },

  down: (queryInterface, Sequelize) => {
    return queryInterface.removeColumn("Users", "password");
  },
};

Kemudian migrasi tersebut kita terapkan ke database dengan perintah berikut.

sequelize db:migrate

https://raw.githubusercontent.com/AsrulLove/img-db/master/tambah-kolom.png

Jika kolom telah kita tambahkan, jangan lupa ubah model agar sesuai dengan tabel. Ubah file user.js sehingga menjadi seperti berikut.

"use strict";
module.exports = (sequelize, DataTypes) => {
  const User = sequelize.define(
    "User",
    {
      name: DataTypes.STRING,
      label: DataTypes.STRING,
      picture: DataTypes.STRING,
      email: DataTypes.STRING,
      phone: DataTypes.STRING,
      website: DataTypes.STRING,
      summary: DataTypes.STRING,
      password: DataTypes.STRING,
    },
    {}
  );
  User.associate = function (models) {
    // associations can be defined here
  };
  return User;
};

Register User

Proses register merupakan proses untuk mendaftarkan identitas yang memiliki kunci untuk masuk kembali. Data yang bersifat sensitif harus kita lakukan encripsi. Pada kasus ini kita butuh library bcryptjs yang berfungsi untuk mengencripsi data. Intall bcryptjs dengan cara.

npm i bcryptjs

Pastikan pada file package.json, bcryptjs telah tersedia.

Ubah function createUser pada file user.controller.js dan tambahkan bcryptjs.

const model = require("../models");
const bcrypt = require("bcryptjs");

function createUser(req, res) {
  let salt = bcrypt.genSaltSync(10);
  let hash = bcrypt.hashSync(req.body.password, salt);

  model.User.create({
    name: req.body.name,
    label: req.body.label,
    picture: req.body.picture,
    email: req.body.email,
    phone: req.body.phone,
    website: req.body.website,
    summary: req.body.summary,
    password: hash,
  })
    .then(function (result) {
      res.json(result);
    })
    .catch(function (error) {
      res.json({ error: error });
    });
}

Perhatikan hasil register pada insomnia.

https://raw.githubusercontent.com/AsrulLove/img-db/master/bycript.png

Token User

Pada sebuah aplikasi setelah seseorang login maka dibutuhkan token sebagai credential terpercaya untuk mengelola data, misal update atau mungkin hapus.

Kalau dicontohkan ke kehidupan nyata email dan password adalah tiket untuk naik pesawat yang ditukarkan saat check in hingga mendapatkan boarding pass. Boarding pass inilah yang kita gunakan untuk masuk ke pesawat. Sama halnya dengan token, token didapatkan setelah login dilakukan, sehingga token dikirim bersamaan dengan akses pada server lebih dalam.

Untuk membuat token kita menggunakan library jsonwebtoken, install dengan cara berikut.

npm i jsonwebtoken

Tambahkan function loginUser pada file user.controller.js, yang isinya seperti berikut.

const model = require("../models");
const bcrypt = require("bcryptjs");
const jwt = require("jsonwebtoken");

function loginUser(req, res) {
  const email = req.body.email;
  const password = req.body.password;

  model.User.findOne({
    where: {
      email: email,
    },
  })
    .then(function (result) {
      let passwordHash = result.password;
      let checkPassword = bcrypt.compareSync(password, passwordHash);

      if (checkPassword) {
        res.json({
          message: "Berhasil Login",
          token: jwt.sign({ id: result.id }, "asrul-dev"),
        });
      } else {
        res.json({
          message: "Gagal Login",
        });
      }
    })
    .catch(function (error) {
      res.json({ error: error });
    });
}

Jangan lupa tambahkan route pada file user.route.js, sehingga menjadi seperti berikut.

const router = require("express").Router();
const userController = require("../controller/user.controller.js");

router.post("/login", userController.loginUser);
router.post("/", userController.createUser);
router.get("/", userController.readUser);
router.put("/:id", userController.updateUser);
router.delete("/:id", userController.deleteUser);

module.exports = router;

Tes menggunakan insomia.

https://raw.githubusercontent.com/AsrulLove/img-db/master/dapat-token.png

Akhirnya berhasil juga, tapi tidak sampai disitu kita harus melakukan autorize, yaitu memberi hak akses terhadap aktifitas data. Seperti update dan delete pada kasus ini hanya boleh dilakukan orang yang memiliki akun tersebut.

Authorize

Penggunaan authorize kita harus membuat middleware, middleware adalah perantara route dan controller, sehingga ketika melewati route menuju controller akan dilakukan pemeriksaan, apakah memiliki autorize atau tidak.

Buat file baru dengan nama auth.js dalam folder middlewares, yang isinya berikut.

const jwt = require("jsonwebtoken");
const model = require("../models");

module.exports = (req, res, next) => {
  let token = req.headers.token;
  if (token) {
    let verify = jwt.verify(token, "asrul-dev");

    model.User.findOne({
      where: {
        id: verify.id,
      },
    })
      .then(function (result) {
        if (result) {
          req.decoded = verify;
          next();
        } else {
          res.status(401).json({
            message: "Kamu tak punya akses",
          });
        }
      })
      .catch(function (error) {
        res.json({ error: error });
      });
  } else {
    res.status(401).json({
      message: "Silahkan Login Dahulu",
    });
  }
};

Kemudian ubah route user.router.js menjadi seperti berikut.

const router = require("express").Router();
const userController = require("../controller/user.controller.js");
const auth = require("../middlewares/auth.js");

router.post("/login", userController.loginUser);
router.post("/", userController.createUser);
router.get("/", userController.readUser);
router.put("/:id", auth, userController.updateUser);
router.delete("/:id", auth, userController.deleteUser);

module.exports = router;

Pada saat update dan delete, jika yang mengakses bukan yang login maka data dilarang diubah atau dihapus. Untuk melakukan itu ubah function updateUser dan function deleteUser menjadi seperti berikut.

function updateUser(req, res) {
  let decodedId = req.decoded.id;

  if (Number(decodedId) === Number(req.params.id)) {
    model.User.update(
      {
        name: req.body.name,
        label: req.body.label,
        picture: req.body.picture,
        email: req.body.email,
        phone: req.body.phone,
        website: req.body.website,
        summary: req.body.summary,
      },
      {
        where: {
          id: req.params.id,
        },
      }
    )
      .then(function (result) {
        res.json(result);
      })
      .catch(function (error) {
        res.json({ error: error });
      });
  } else {
    res.json({
      message: "Ini bukan data Anda",
    });
  }
}

function deleteUser(req, res) {
  let decodedId = req.decoded.id;

  if (Number(decodedId) === Number(req.params.id)) {
    model.User.destroy({
      where: {
        id: req.params.id,
      },
    })
      .then(function (result) {
        res.json(result);
      })
      .catch(function (error) {
        res.json({ error: error });
      });
  } else {
    res.json({
      message: "Ini bukan data Anda",
    });
  }
}

Kita uji pada insomnia dengan skenario, token adalah milik user dengan id 3, tetapi yang akan dihapus adalah user id 4.

https://raw.githubusercontent.com/AsrulLove/img-db/master/gagal-hapus.png

No Comments Yet