Cara Mengamankan API REST Node.js Menggunakan Token Web JSON
Table of content:
Saat membuat aplikasi, penting bagi Anda untuk melindungi data sensitif dari akses tidak sah. Banyak aplikasi web, seluler, dan cloud modern menggunakan REST API sebagai alat komunikasi utama. Akibatnya, sangat penting untuk merancang dan mengembangkan API backend dengan keamanan di garis depan.
Salah satu pendekatan efektif untuk mengamankan REST API melibatkan JSON Web Token (JWT). Token ini menawarkan mekanisme yang kuat untuk autentikasi dan otorisasi pengguna, membantu melindungi sumber daya yang dilindungi dari akses oleh pelaku jahat.
Apa itu Token Web JSON?
Token Web JSON (JWT) adalah standar keamanan yang banyak digunakan. Ini menyediakan metode mandiri yang ringkas untuk mentransmisikan data dengan aman antara aplikasi klien dan sistem backend.
REST API dapat menggunakan JWT untuk mengidentifikasi dan mengautentikasi pengguna dengan aman saat mereka membuat permintaan HTTP untuk mengakses sumber daya yang dilindungi.
Token Web JSON terdiri dari tiga bagian berbeda: header, payload, dan tanda tangan. Itu mengkodekan setiap bagian dan menggabungkannya menggunakan tanda titik (“.”).
Header menjelaskan algoritme kriptografi yang digunakan untuk menandatangani token, sedangkan payload berisi data tentang pengguna dan metadata tambahan apa pun.
Terakhir, tanda tangan, yang dihitung menggunakan header, payload, dan kunci rahasia, memastikan integritas dan keaslian token.
Dengan dasar-dasar JWT, mari kita membangun REST API Node.js dan mengimplementasikan JWT.
Menyiapkan Aplikasi Express.js dan Database MongoDB
Anda akan menemukan di sini cara membuat API REST autentikasi sederhana yang menangani fungsi pendaftaran dan masuk. Setelah proses login mengautentikasi pengguna, mereka harus dapat membuat permintaan HTTP ke rute API yang dilindungi.
Untuk memulai, buat server web Express, dan instal paket berikut:
npm install cors dotenv bycrpt mongoose cookie-parser crypto jsonwebtoken mongodb
Selanjutnya, buat database MongoDB atau konfigurasikan cluster MongoDB di cloud. Kemudian salin string koneksi database, buat a .env file di direktori root, dan rekatkan di string koneksi:
CONNECTION_STRING="connection string"
Konfigurasi Koneksi Database
Buat yang baru utils/db.js file di direktori root folder proyek Anda. Dalam file ini, tambahkan kode berikut untuk membuat koneksi database menggunakan Mongoose.
const mongoose = require('mongoose');const connectDB = async () => {
try {
await mongoose.connect(process.env.CONNECTION_STRING);
console.log("Connected to MongoDB!");
} catch (error) {
console.error("Error connecting to MongoDB:", error);
}
};
module.exports = connectDB;
Tentukan Model Data
Tentukan skema data pengguna sederhana menggunakan Mongoose. Di direktori root, buat yang baru model/pengguna.model.js file dan tambahkan kode berikut.
const mongoose = require('mongoose');const userSchema = new mongoose.Schema({
username: String,
password: {
type: String,
required: true,
unique: true,
},
});
const User = mongoose.model("User", userSchema);
module.exports = User;
Tentukan Pengontrol untuk Rute API
Fungsi pengontrol akan mengelola pendaftaran dan login; mereka adalah bagian penting dari contoh program ini. Di direktori root, buat a controllers/userControllers.js file dan tambahkan kode berikut:
- Tentukan pengontrol pendaftaran pengguna.
const User = require('../models/user.model');
const bcrypt = require('bcrypt');
const { generateToken } = require('../middleware/auth');exports.registerUser = async (req, res) => {
const { username, password } = req.body;try {
const hash = await bcrypt.hash(password, 10);
await User.create({ username, password: hash });
res.status(201).send({ message: 'User registered successfully' });
} catch (error) {
console.log(error);
res.status(500).send({ message: 'An error occurred!! ' });
}
};Cuplikan kode ini mem-hash kata sandi yang diberikan menggunakan bcrypt dan kemudian membuat catatan pengguna baru di database, menyimpan nama pengguna dan kata sandi yang di-hash. Jika pendaftaran berhasil, ia mengirimkan respons dengan pesan sukses.
- Tetapkan pengontrol login untuk mengelola proses login pengguna:
exports.loginUser = async (req, res) => {
const { username, password } = req.body;try {
const user = await User.findOne({ username });
if (!user) {
return res.status(404).send({ message: 'User not found' });
}const passwordMatch = await bcrypt.compare(password, user.password);
if (!passwordMatch) {
return res.status(401).send({ message: 'Invalid login credentials' });
}const payload = { userId: user._id };
const token = generateToken(payload);
res.cookie('token', token, { httpOnly: true });
res.status(200).json({ message: 'Login successful'});
} catch (error) {
console.log(error);
res.status(500).send({ message: 'An error occurred while logging in' });
}
};Saat pengguna mengirim permintaan ke /Gabung rute, mereka harus melewati kredensial otentikasi mereka di badan permintaan. Kode kemudian memverifikasi kredensial tersebut dan menghasilkan Token Web JSON. Token disimpan dengan aman dalam cookie dengan httpOnly bendera disetel ke true. Ini mencegah JavaScript sisi klien mengakses token, melindungi dari potensi serangan cross-site scripting (XSS).
- Terakhir, tentukan rute yang dilindungi:
exports.getUsers = async (req, res) => {
try {
const users = await User.find({});
res.json(users);
} catch (error) {
console.log(error);
res.status(500).send({ message: 'An error occurred!!' });
}
};Dengan menyimpan JWT dalam cookie, permintaan API selanjutnya dari pengguna yang diautentikasi akan secara otomatis menyertakan token, memungkinkan server memvalidasi dan mengesahkan permintaan.
Buat Middleware Otentikasi
Sekarang setelah Anda menentukan pengontrol masuk yang menghasilkan token JWT setelah otentikasi berhasil, tentukan fungsi otentikasi middleware yang akan menghasilkan dan memverifikasi token JWT.
Di direktori root, buat folder baru, middleware. Di dalam folder ini, tambahkan dua file: auth.js Dan config.js.
Tambahkan kode ini ke config.js:
const crypto = require('crypto');module.exports = {
secretKey: crypto.randomBytes(32).toString('hex')
};
Kode ini menghasilkan kunci rahasia acak baru setiap kali dijalankan. Anda kemudian dapat menggunakan kunci rahasia ini untuk menandatangani dan memverifikasi keaslian JWT. Setelah pengguna berhasil diautentikasi, buat dan tandatangani JWT dengan kunci rahasia. Server kemudian akan menggunakan kunci untuk memverifikasi bahwa JWT valid.
Tambahkan kode berikut di auth.js yang mendefinisikan fungsi middleware yang menghasilkan dan memverifikasi JWT.
const jwt = require('jsonwebtoken');
const { secretKey } = require('./config');const generateToken = (payload) => {
const token = jwt.sign(payload, secretKey, { expiresIn: '1h' });
return token ;
};
const verifyToken = (req, res, next) => {
const token = req.cookies.token;
if (!token) {
return res.status(401).json({ message: 'No token provided' });
}
jwt.verify(token, secretKey, (err, decoded) => {
if (err) {
return res.status(401).json({ message: 'Invalid token' });
}
req.userId = decoded.userId;
next();
});
};
module.exports = { generateToken, verifyToken };
Itu generateToken fungsi menghasilkan JWT dengan menandatangani payload menggunakan kunci rahasia dan mengatur waktu kedaluwarsa sementara verifikasiToken fungsi berfungsi sebagai middleware untuk memverifikasi keaslian dan validitas token yang disediakan.
Tentukan Rute API
Buat yang baru rute/userRoutes.js file di direktori root dan tambahkan kode berikut.
const express = require('express');
const router = express.Router();
const userControllers = require('../controllers/userControllers');
const { verifyToken } = require('../middleware/auth');
router.post('/api/register', userControllers.registerUser);
router.post('/api/login', userControllers.loginUser);
router.get('/api/users', verifyToken, userControllers.getUsers);
module.exports = router;
Perbarui Titik Masuk Server Anda
Perbarui Anda server.js file dengan kode berikut.
const express = require('express');
const cors = require('cors');
const app = express();
const port = 5000;
require('dotenv').config();
const connectDB = require('./utils/db');
const cookieParser = require('cookie-parser');connectDB();
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.use(cors());
app.use(cookieParser());
const userRoutes = require('./routes/userRoutes');
app.use("https://www.makeuseof.com/", userRoutes);
app.listen(port, () => {
console.log(`Server is listening at http://localhost:${port}`);
});
Untuk menguji REST API, aktifkan server pengembangan dan buat permintaan API ke titik akhir yang ditentukan:
node server.js
Mengamankan REST API Node.js
Mengamankan REST API Node.js lebih dari sekadar menggunakan JWT, meskipun JWT memainkan peran penting dalam autentikasi dan otorisasi, penting untuk mengadopsi pendekatan keamanan menyeluruh terhadap keamanan untuk melindungi sistem backend Anda. Di samping JWT, Anda juga harus mempertimbangkan penerapan HTTPS untuk mengenkripsi komunikasi, validasi input dan sanitasi, dan banyak lainnya.
Dengan menggabungkan beberapa tindakan keamanan, Anda dapat membuat kerangka kerja keamanan yang kuat untuk API REST Node.js Anda dan meminimalkan risiko akses tidak sah, pelanggaran data, dan ancaman keamanan lainnya.