Что такое JSON Web Token?

Ответ

JSON Web Token (JWT) — это компактный, URL-безопасный способ представления утверждений (claims), которые должны быть переданы между двумя сторонами. В веб-разработке на Node.js JWT чаще всего используется как стандарт для токенов доступа в stateless-аутентификации.

Структура токена (Header.Payload.Signature):

  • Header: Содержит тип токена (typ: "JWT") и алгоритм подписи (alg, например, HS256 или RS256).
  • Payload: Содержит утверждения (claims) — данные о пользователе (например, userId, role) и служебную информацию (iss — издатель, exp — срок действия).
  • Signature: Создается путём кодирования header и payload по алгоритму Base64Url, их объединения и подписи с использованием секретного ключа (для HS256) или приватного ключа (для RS256). Подпись обеспечивает целостность токена.

Пример работы с JWT в Node.js (библиотека jsonwebtoken):

const jwt = require('jsonwebtoken');
const SECRET_KEY = process.env.JWT_SECRET; // Хранить в переменных окружения!

// 1. Создание (подписание) токена при успешном логине
function generateAccessToken(user) {
  return jwt.sign(
    { 
      userId: user.id, 
      role: user.role 
    }, // Payload
    SECRET_KEY,
    { expiresIn: '15m' } // Токен действует 15 минут
  );
}

// 2. Верификация и декодирование токена в middleware
function authenticateToken(req, res, next) {
  const authHeader = req.headers['authorization'];
  const token = authHeader && authHeader.split(' ')[1]; // Извлечь токен из 'Bearer <token>'

  if (!token) return res.sendStatus(401);

  jwt.verify(token, SECRET_KEY, (err, user) => {
    if (err) return res.sendStatus(403); // Токен невалиден или просрочен
    req.user = user; // Добавляем данные из payload в объект запроса
    next();
  });
}

Важные моменты:

  • JWT не зашифрован, а только закодирован и подписан. Не храните в payload конфиденциальные данные.
  • Для обеспечения безопасности используйте короткое время жизни Access Token и механизм Refresh Token.
  • Подпись HS256 использует один секретный ключ, RS256 — пару приватный/публичный ключ, что безопаснее для распределённых систем.

Ответ 18+ 🔞

Э, слушай, давай разберем эту вашу моду, про которую все так носятся — JSON Web Token, или просто JWT. Выглядит как абракадабра из трёх кусков, разделённых точками, а на деле — просто способ сказать: «Чувак, я свой, пусти».

Из чего эта штука состоит, или «Раздевай токен, показывай claims»:

  • Header (Заголовок): Тут всё просто, как три копейки. Тип — "JWT", и алгоритм, которым эту хрень подписали (например, HS256). Всё это в Base64, чтобы не ломать глаза.
  • Payload (Полезная нагрузка): А вот тут самое интересное лежит. Всё, что ты туда запихнул: userId, role, срок годности (exp). Помни, что это не зашифровано, а просто закодировано! Любой мудак может декодировать и посмотреть. Так что не пихай туда пароль бабушки или размер своего достоинства.
  • Signature (Подпись): Вот тут и кроется вся магия, не дающая токену превратиться в манду с ушами. Берется закодированные header и payload, склеиваются, и эта солянка подписывается секретным ключом (или приватным, если алгоритм посерьёзнее). Если кто-то попробует в payload что-то поменять — подпись не сойдётся, и токен накроется медным тазом.

Как с этим жить в Node.js (библиотека jsonwebtoken):

const jwt = require('jsonwebtoken');
const SECRET_KEY = process.env.JWT_SECRET; // Храни ключ в окружении, а не в коде, распиздяй!

// 1. Создаём токен, когда пользователь залогинился
function generateAccessToken(user) {
  return jwt.sign(
    { 
      userId: user.id, 
      role: user.role 
    }, // Вот это всё улетит в payload
    SECRET_KEY,
    { expiresIn: '15m' } // Живёт 15 минут. Не делай вечные токены — это пиздец как небезопасно.
  );
}

// 2. Проверяем каждый раз, когда чувак стучится к нам
function authenticateToken(req, res, next) {
  const authHeader = req.headers['authorization'];
  // Вытаскиваем токен из заголовка 'Bearer <token>'. Если его нет — сразу 401, иди нахуй.
  const token = authHeader && authHeader.split(' ')[1];

  if (!token) return res.sendStatus(401);

  // А вот тут сама верификация. Если токен просрочен или подпись кривая — получишь 403.
  jwt.verify(token, SECRET_KEY, (err, user) => {
    if (err) return res.sendStatus(403);
    req.user = user; // Если всё ок — кладём расшифрованные данные в запрос
    next();
  });
}

На что смотреть, чтобы не обосраться:

  • Повторю, как мантру: JWT НЕ ШИФРУЕТ. Он только кодирует и подписывает. Все данные в payload — на виду. Доверия ебать ноль к тому, что там лежит, если ты сам это не положил и не подписал.
  • Access Token должен жить недолго (минуты). Для долгой сессии используй связку Access + Refresh Token, иначе любой, кто украл токен, будет гулять по твоему API, пока тот не протухнет.
  • HS256 — симметричная подпись, один ключ и для создания, и для проверки. Просто, но если ключ утечёт — пидарас шерстяной, всем пизда. RS256 (публичный/приватный ключ) — надёжнее для микросервисов.