tech

Table of Content

Introduction

Lanjutan dari materi 10. Restful API Menggunakan TypeORM,

Install

npm install jsonwebtoken

Login

app.js

const jwt = require('jsonwebtoken');
const JWT_SECRET = 'rahasia-super-aman-123';
 
app.post('/login', async (req, res) => {
  try {
    const { email, password } = req.body;
 
    if (!email || !password) {
      return res.status(400).json({ error: 'Email dan password wajib diisi' });
    }
 
    const user = await User.findOne({ where: { email } });
    if (!user) {
      return res.status(401).json({ error: 'Email atau password salah' });
    }
 
    const isPasswordValid = await bcrypt.compare(password, user.password);
    if (!isPasswordValid) {
      return res.status(401).json({ error: 'Email atau password salah' });
    }
 
    const token = jwt.sign(
      { id: user.id, email: user.email }, 
      JWT_SECRET,
      { expiresIn: '1h' } 
    );
 
    res.json({
      message: 'Login berhasil',
      token,
      user: {
        id: user.id,
        nama: user.nama,
        email: user.email
      }
    });
  } catch (error) {
    console.error('Error saat login:', error);
    res.status(500).json({ error: 'Gagal melakukan login' });
  }
});

Penjelasan:

  • jwt.sign(): untuk membuat jwt token nya.
  • expiresIn: untuk menetapkan batas habis token nya.

Middleware

app.js

function authenticateToken(req, res, next) {
  const authHeader = req.headers['authorization'];
  const token = authHeader && authHeader.split(' ')[1]; 
 
  if (!token) {
    return res.status(401).json({ error: 'Akses ditolak. Token diperlukan.' });
  }
 
  jwt.verify(token, JWT_SECRET, (err, user) => {
    if (err) {
      return res.status(403).json({ error: 'Token tidak valid.' });
    }
    req.user = user; 
    next();
  });
}

Protect Route

app.get('/users', authenticateToken, async (req, res) => {
// ...
}

Cukup panggil function setelah alamat route nya…

Cara Memasukkan JWT

  • Masukkan di header key “Authorization”
  • Value nya “Barer key nya” (pakai spasi ya).

Full Code nya

const express = require('express');
const bcrypt = require('bcrypt');
const User = require('./models/Users');
const sequelize = require('./config/db');
const app = express();
const jwt = require('jsonwebtoken');
const JWT_SECRET = 'rahasia-super-aman-123';
const PORT = process.env.PORT || 3000;
 
const SALT_ROUNDS = 10;
 
app.use(express.json());
 
function authenticateToken(req, res, next) {
  const authHeader = req.headers['authorization'];
  const token = authHeader && authHeader.split(' ')[1]; 
 
  if (!token) {
    return res.status(401).json({ error: 'Akses ditolak. Token diperlukan.' });
  }
 
  jwt.verify(token, JWT_SECRET, (err, user) => {
    if (err) {
      return res.status(403).json({ error: 'Token tidak valid.' });
    }
    req.user = user; 
    next();
  });
}
 
app.post('/login', async (req, res) => {
  try {
    const { email, password } = req.body;
 
    if (!email || !password) {
      return res.status(400).json({ error: 'Email dan password wajib diisi' });
    }
 
    const user = await User.findOne({ where: { email } });
    if (!user) {
      return res.status(401).json({ error: 'Email atau password salah' });
    }
 
    const isPasswordValid = await bcrypt.compare(password, user.password);
    if (!isPasswordValid) {
      return res.status(401).json({ error: 'Email atau password salah' });
    }
 
    const token = jwt.sign(
      { id: user.id, email: user.email }, 
      JWT_SECRET,
      { expiresIn: '1h' } 
    );
 
    res.json({
      message: 'Login berhasil',
      token,
      user: {
        id: user.id,
        nama: user.nama,
        email: user.email
      }
    });
  } catch (error) {
    console.error('Error saat login:', error);
    res.status(500).json({ error: 'Gagal melakukan login' });
  }
});
 
app.get('/users', authenticateToken, async (req, res) => {
  try {
    const users = await User.findAll({
      attributes: { exclude: ['password'] } 
    });
    res.json(users);
  } catch (error) {
    console.error(error);
    res.status(500).json({ error: 'Server error saat mengambil data' });
  }
});
 
app.get('/users/:id', authenticateToken, async (req, res) => {
  try {
    const { id } = req.params;
    const user = await User.findByPk(id, {
      attributes: { exclude: ['password'] }
    });
 
    if (!user) {
      return res.status(404).json({ error: 'User tidak ditemukan' });
    }
 
    res.json(user);
  } catch (error) {
    console.error(error);
    res.status(500).json({ error: 'Server error saat mengambil user' });
  }
});
 
app.post('/users', async (req, res) => {
  try {
    const { nama, email, password } = req.body;
 
    if (!nama || !email || !password) {
      return res.status(400).json({ error: 'nama, email, dan password wajib diisi' });
    }
 
    const existingUser = await User.findOne({ where: { email } });
    if (existingUser) {
      return res.status(409).json({ error: 'Email sudah terdaftar' });
    }
 
    const hashedPassword = await bcrypt.hash(password, SALT_ROUNDS);
 
    const user = await User.create({
      nama,
      email,
      password: hashedPassword
    });
 
    const userResponse = {
      id: user.id,
      nama: user.nama,
      email: user.email,
      createdAt: user.createdAt
    };
 
    res.status(201).json(userResponse);
  } catch (error) {
    console.error('Error saat membuat user:', error);
    if (error.nama === 'SequelizeValidationError' || error.nama === 'SequelizeUniqueConstraintError') {
      return res.status(400).json({ error: 'Data tidak valid' });
    }
    res.status(500).json({ error: 'Gagal membuat user' });
  }
});
 
app.put('/users/:id', authenticateToken, async (req, res) => {
  try {
    const { id } = req.params;
    const { nama, email, password } = req.body;
 
    const user = await User.findByPk(id);
    if (!user) {
      return res.status(404).json({ error: 'User tidak ditemukan' });
    }
 
    if (email && email !== user.email) {
      const existingUser = await User.findOne({ where: { email } });
      if (existingUser) {
        return res.status(409).json({ error: 'Email sudah digunakan oleh user lain' });
      }
    }
 
    const updateData = {};
    if (nama !== undefined) updateData.nama = nama;
    if (email !== undefined) updateData.email = email;
 
    if (password !== undefined) {
      const hashedPassword = await bcrypt.hash(password, SALT_ROUNDS);
      updateData.password = hashedPassword;
    }
 
    await user.update(updateData);
 
    const userResponse = {
      id: user.id,
      nama: user.nama,
      email: user.email,
      updatedAt: user.updatedAt
    };
 
    res.json(userResponse);
  } catch (error) {
    console.error('Error saat memperbarui user:', error);
    if (error.name === 'SequelizeValidationError' || error.name === 'SequelizeUniqueConstraintError') {
      return res.status(400).json({ error: 'Data tidak valid' });
    }
    res.status(500).json({ error: 'Gagal memperbarui user' });
  }
});
 
app.delete('/users/:id', authenticateToken, async (req, res) => {
  try {
    const { id } = req.params;
 
    const user = await User.findByPk(id);
    if (!user) {
      return res.status(404).json({ error: 'User tidak ditemukan' });
    }
 
    await user.destroy(); 
    res.status(204).send(); 
  } catch (error) {
    console.error('Error saat menghapus user:', error);
    res.status(500).json({ error: 'Gagal menghapus user' });
  }
});
 
app.listen(PORT, () => {
  console.log(`Server berjalan di http://localhost:${PORT}`);
});

Date: 12-10-2025