Как работает авторизация с использованием JWT (JSON Web Token)?

«Как работает авторизация с использованием JWT (JSON Web Token)?» — вопрос из категории Безопасность, который задают на 10% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

JWT (JSON Web Token) — это открытый стандарт (RFC 7519) для создания токенов доступа, которые позволяют безопасно передавать утверждения (claims) между сторонами. Токен представляет собой компактную строку в формате header.payload.signature.

Структура токена:

  1. Header — определяет алгоритм подписи (например, HS256) и тип токена.
    {
      "alg": "HS256",
      "typ": "JWT"
    }
  2. Payload — содержит утверждения (данные) о пользователе (например, sub, roles, exp).
  3. Signature — создается путем кодирования header и payload с использованием секретного ключа и алгоритма, указанного в header. Гарантирует целостность токена.

Типичный flow авторизации:

  1. Клиент аутентифицируется (логин/пароль).
  2. Сервер проверяет учетные данные и генерирует JWT, подписывая его секретным ключом.
  3. Сервер отправляет JWT клиенту.
  4. Клиент включает JWT в заголовок последующих запросов: Authorization: Bearer <token>.
  5. Сервер проверяет подпись и срок действия токена, извлекает данные из payload для авторизации.

Пример генерации и проверки (Java, jjwt):

// Генерация токена
String secret = "your-256-bit-secret";
String jwt = Jwts.builder()
    .setSubject("user123")
    .claim("role", "ADMIN")
    .setExpiration(new Date(System.currentTimeMillis() + 3600000))
    .signWith(SignatureAlgorithm.HS256, secret.getBytes())
    .compact();

// Проверка токена
Claims claims = Jwts.parser()
    .setSigningKey(secret.getBytes())
    .parseClaimsJws(jwt)
    .getBody();
String username = claims.getSubject(); // "user123"
Преимущества и недостатки: Преимущество Недостаток
Stateless: Серверу не нужно хранить состояние сессии. Немедленный отзыв: Скомпрометированный токен действует до истечения срока (exp). Для отзыва требуются черные списки (blacklist) или короткие сроки жизни.
Масштабируемость: Любой сервер с ключом может проверить токен. Размер: Токен передается в каждом запросе, может быть больше, чем session ID.
Самоописание: Payload содержит полезные данные. Безопасность: Ключ подписи должен храниться в секрете. Payload не шифруется по умолчанию (используйте JWE для конфиденциальных данных).