🚀 Вышла книга Build Layered Microservices! Купите себе копию прямо сейчас на learnbackend.dev.

Веб-токен JSON, часто сокращенно JWT (произносится как «джот»), представляет собой компактный, автономный токен с цифровой подписью, который использует формат JSON для передачи информации между сторонами.

Помимо метода шифрования, популярным его делает использование формата JSON, который намного компактнее, чем, например, XML, что упрощает манипулирование в Интернете и, как правило, проще в использовании, поскольку синтаксические анализаторы JSON довольно распространены в большинстве программ. языки.

В этой статье вы узнаете, как подписывать и декодировать веб-токены JSON в Node.js с помощью пакета jsonwebtoken.

Анатомия JWT

JWT состоит из трех частей: заголовок, полезная нагрузка и подпись, где каждая часть разделена точечным символом.

header.payload.signature

JWT-заголовок

Заголовок представляет собой закодированный Base64Url объект, состоящий из двух полей: тип токена и алгоритм подписи.

{
  "typ": "JWT",
  "alg": "HS256"
}

Полезная нагрузка JWT

Полезная нагрузка также представляет собой закодированный Base64Url объект, содержащий фрагменты информации об объекте (обычно о пользователе) и дополнительные данные, называемые заявками, которые могут быть трех типов:

  • Зарегистрированные заявки – это необязательные предварительно определенные заявки, которые можно указать для обеспечения взаимодействия со сторонними или внешними приложениями, такими как эмитент токена или срок его действия.
  • Общедоступные претензии обычно представляют собой общую неконфиденциальную информацию, такую ​​как полное имя пользователя или адрес электронной почты.
  • Частные претензии обычно представляют собой специфичную для приложения и конфиденциальную информацию, например внутренний идентификатор пользователя.
{
  "exp": 1638298179,            // registered
  "name": "John Doe",           // public
  "email": "[email protected]",  // public
  "internal_id": "admin1234"    // private
}

Подпись JWT

Наконец, подпись создается с использованием комбинации алгоритма, указанного в заголовке, секретного значения и объединенного в точку значения закодированного заголовка и полезной нагрузки.

HmacSHA256(
  secret,
  base64url(header) + '.' + base64url(payload)
)

Пакет jsonwebtoken

Самый популярный пакет для управления JWT в Node.js — jsonwebtoken, его можно установить с помощью следующей команды:

$ npm install --save jsonwebtoken

Подписание нового JWT

Чтобы сгенерировать (то есть подписать) новый веб-токен JSON, мы можем использовать метод sign() верхнего уровня, который принимает три аргумента:

  • Полезная нагрузка, то есть данные, которые мы хотим отправить клиенту (например, идентификатор пользователя).
  • секрет или закрытый ключ, который представляет собой либо строку символов (например, «myJWTSecret»), либо файл PEM, который можно сгенерировать с помощью такого инструмента, как ssh-keygen.
  • Необязательный объект options, который содержит дополнительные или метаданные, такие как алгоритм, срок действия или эмитент токена (ср. претензии).
const jwt = require('jsonwebtoken');

const payload = {
  name: "John"
};
const secret = "mysecret";
const token = jwt.sign(payload, secret);

console.log(token);

Запуск вышеуказанного скрипта приведет к следующему выводу:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoiSm9obiIsImlhdCI6MTY1OTAwODQxMH0.w-z_Ht5B4PLQFUQJhymbERqudUboCVtmM24t2y-UjsE

Определение срока годности

Каждая часть информации, которая проходит через такие сети, как Интернет, потенциально может быть украдена. По этой причине обычно рекомендуется определять дату истечения срока действия JWT, чтобы украденный токен не предоставлял злоумышленнику неограниченный доступ к защищенному ресурсу.

Первый метод состоит в определении утверждения exp в объекте payload, которое содержит количество секунд до истечения срока действия, начиная с Эпохи (01 января 1970 г.).

const jwt = require('jsonwebtoken');

const payload = {
  name: "John",
  exp: Math.floor(Date.now() / 1000) + (60 * 60)  // 1h
};
const secret = "mysecret";
const token = jwt.sign(payload, secret);

Второй метод заключается в добавлении поля expiresIn к объекту options, которое содержит строку символов, описывающую промежуток времени.

const jwt = require('jsonwebtoken');

const payload = {
  name: "John"
};
const secret = "mysecret";
const options = {
  expiresIn: "1h"
};
const token = jwt.sign(payload, secret, options);

Расшифровка JWT

Чтобы декодировать веб-токен JSON, мы можем использовать экспортируемый модулем метод верхнего уровня verify(), который принимает три аргумента:

  • токен, представляющий собой веб-токен JSON для декодирования.
  • секретный или открытый ключ, который представляет собой либо строку символов (например, «myJWTSecret»), либо файл PEM, который можно создать с помощью такого инструмента, как ssh-keygen.
  • Необязательный объект options для выполнения дополнительных проверок токена.
const jwt = require('jsonwebtoken');

const token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoiSm9obiIsImlhdCI6MTY1OTAwODQxMH0.w-z_Ht5B4PLQFUQJhymbERqudUboCVtmM24t2y-UjsE";
const secret = "mysecret";
const payload = jwt.decode(token, secret);

console.log(payload);

Запуск вышеуказанного скрипта приведет к следующему выводу:

{ name: 'John', iat: 1659008410 }

Что дальше?

👉 Нравится ли вам такой контент? Ознакомьтесь с книгой Создание многоуровневых микросервисов на https://learnbackend.dev о том, как создать готовый к эксплуатации микросервис многоуровневой аутентификации с использованием платформы Express, который соответствует отраслевым стандартам в с точки зрения практики разработки и архитектуры программного обеспечения от первой строки кода до последней строки документации.