Аутентифікація є важливою частиною бекенд-розробки. Вона допомагає визначити, який користувач робить запит до вашого додатку, і дозволяє обмежити доступ до певних маршрутів. Авторизація була реалізована різними способами з часом, і одним з найпоширеніших і потужних методів сьогодні є використання JWT (JSON Web Token). У цій статті ми розглянемо, як реалізувати аутентифікацію JWT в додатку на Express.js з мінімальними зусиллями, незалежно від вашого потоку аутентифікації.
Можливо, ви запитаєте: "Як це застосовується, коли я використовую систему email/пароль, систему OTP або інший метод аутентифікації?" Давайте розберемося.
Крок 1: Встановлення необхідного пакету
Перший крок — це встановлення пакету, необхідного для авторизації на основі JWT: jsonwebtoken
. Встановіть його за допомогою npm:
npm install jsonwebtoken
Крок 2: Розуміння того, як працює JWT
Перед тим, як перейти до коду, давайте розберемося з основами того, як працює JWT.
Кожен запит до захищеного ендпоінта повинен включати заголовок Authorization
. Цей заголовок працює як бейдж, і якщо він відсутній, проміжне програмне забезпечення (middleware), яке працює як охоронець, заблокує запит і поверне помилку 403 Forbidden
.
Якщо заголовок Authorization
присутній, проміжне програмне забезпечення буде:
- Перевіряти, чи є токен дійсним і не простроченим.
- Декодувати токен, щоб отримати інформацію про користувача (наприклад, ідентифікатор користувача).
- Запитати базу даних, щоб отримати дані користувача.
- Прикріпити інформацію про користувача до об'єкта
req
і дозволити запиту продовжити виконання.
Токени, згенеровані за допомогою JWT, мають час життя. Коли токен прострочений, користувач повинен знову увійти в систему або використати refresh token (це поза межами цієї статті).
Крок 3: Захист маршрутів
Щоб захистити ваші маршрути, вам потрібно використовувати проміжне програмне забезпечення (middleware), яке перевіряє JWT токен. Ось приклад того, як захистити маршрут, додавши проміжне програмне забезпечення перед методом контролера:
userRouter.route('/profile').get(
multer().none(),
authorizeRequest,
userController.getUserProfile
);
У цьому прикладі маршрут /profile
захищений за допомогою проміжного програмного забезпечення authorizeRequest
. Проміжне програмне забезпечення перевіряє JWT токен перед виконанням методу контролера getUserProfile
.
Крок 4: Проміжне програмне забезпечення для авторизації JWT
Нижче наведено проміжне програмне забезпечення, яке ви можете використовувати для захисту своїх маршрутів:
export function authorizeRequest(req, res, next) {
// Отримати заголовок Authorization
let header = req.headers.Authorization || req.headers.authorization;
// Перевірити, чи існує заголовок і чи починається він з "Bearer"
if (!header || !header.startsWith("Bearer")) {
return next({ status: 401, message: "Unauthorized request" });
}
// Витягнути токен з заголовка
const token = header.split(" ")[1];
// Якщо токен не знайдений
if (!token) {
return next({ status: 401, message: "Unauthorized request" });
}
// Перевірити токен
jwt.verify(token, process.env.JWT_PASS, async (err, decoded) => {
if (err) {
return next({ status: 401, message: "Unauthorized request" });
}
// Запитати базу даних для користувача
let user = await User.findOne({
where: { id: decoded.id, is_active: true, blocked: false },
attributes: { exclude: ['password', 'is_active', 'blocked'] }
});
// Якщо користувача не знайдено
if (!user) {
return next({ status: 401, message: "Unauthorized request" });
}
// Прикріпити користувача до об'єкта запиту
req.user = user;
return next();
});
}
Як працює проміжне програмне забезпечення
- Перевірка заголовка: Проміжне програмне забезпечення перевіряє, чи існує заголовок
Authorization
і чи починається він з "Bearer". Якщо це не так, запит відхиляється. - Витягування токена: Токен витягується шляхом розділення значення заголовка після пробілу, що йде після "Bearer".
- Перевірка токена: Токен перевіряється за допомогою методу
verify
з пакетуjsonwebtoken
.
Якщо токен прострочений або недійсний, повертається помилка. - Запит до бази даних: Ідентифікатор користувача, що зберігається в токені, використовується для запиту до бази даних для отримання відповідного користувача. Додаткові фільтри (наприклад,
is_active
іblocked
) забезпечують, що користувач все ще має право доступу до системи. - Прикріплення до запиту: Якщо користувач існує і токен є дійсним, його інформація прикріплюється до об'єкта
req
для використання в подальших обробниках маршрутів.
Крок 5: Створення JWT токена
JWT токени зазвичай генеруються під час входу користувача або аутентифікації. Наприклад, коли перевіряється email/пароль користувача або OTP, ви генеруєте токен.
Ось як можна створити токен:
export function generateJWT(userId, role) {
let token = jwt.sign(
{
id: userId,
role,
},
process.env.JWT_PASS,
{
expiresIn: "1y",
}
);
return token;
}
Як працює GenerateJWT:
Ця функція використовує метод sign
з пакету jsonwebtoken
для генерації токена.
id
таrole
включаються в payload для ідентифікації користувача та його ролі.- Секретний ключ (
JWT_PASS
) з файлу середовища використовується для кодування та декодування токена. - Токен має термін дії один рік (
1y
).
Крок 6: Організація файлів
Для кращої структури та зручності обслуговування рекомендується організувати ваші файли:
- Розмістіть проміжне програмне забезпечення (
authorizeRequest
) в окремому файлі, наприклад,auth.middleware.js
, щоб вказати його призначення. - Розмістіть функцію генерації токенів (
generateJWT
) в утилітному файлі, наприклад,functions.util.js
, оскільки це повторно використовувана функція.
Висновок
У цій статті ми розглянули, як реалізувати аутентифікацію JWT в додатку на Express.js. Зрозумівши, як працює JWT, створюючи токени та перевіряючи їх за допомогою проміжного програмного забезпечення, ви можете ефективно захищати свої маршрути та контролювати доступ до вашого додатку.
Сподіваюся, що цей посібник допоможе вам почати використовувати аутентифікацію JWT у ваших проектах!
Перекладено з: Implementing JWT Authentication in Express.js