Каков жизненный цикл JWT-токена при аутентификации?

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

Ответ

Аутентификация с использованием JWT (JSON Web Token) — это stateless-процесс, основанный на обмене подписанными токенами. Жизненный цикл токена включает генерацию, использование и валидацию.

Процесс аутентификации:

  1. Запрос на аутентификацию. Клиент отправляет свои учетные данные (например, логин и пароль) на специальный эндпоинт сервера (например, /api/login).
  2. Валидация и генерация токена. Сервер проверяет учетные данные. В случае успеха он создает JWT, который состоит из трех частей: заголовка (header), полезной нагрузки (payload) и подписи (signature).
    • В payload обычно включают идентификатор пользователя (sub или user_id), роли (roles) и время истечения срока действия (exp).
    • Сервер подписывает токен секретным ключом (для симметричного шифрования HS256) или приватным ключом ( для асимметричного RS256).
  3. Передача токена клиенту. Сервер возвращает сгенерированный JWT клиенту в теле ответа.
  4. Использование токена. Клиент сохраняет токен (например, в localStorage или в безопасных HttpOnly cookie) и прикрепляет его к каждому последующему запросу к защищенным ресурсам в заголовке Authorization.
    Authorization: Bearer <your_jwt_token>
  5. Валидация на сервере. При каждом запросе сервер (или API-шлюз) извлекает токен из заголовка, проверяет его подпись с помощью своего секретного ключа и валидность payload (например, не истек ли срок действия exp). Если все в порядке, запрос обрабатывается.

Пример на Python (PyJWT):

import jwt
from datetime import datetime, timedelta, timezone

# Секретный ключ, должен храниться в безопасности
SECRET_KEY = "your-super-secret-key"

# 1. Генерация токена после успешной аутентификации
payload = {
    "sub": 12345, # Идентификатор пользователя
    "exp": datetime.now(timezone.utc) + timedelta(hours=1), # Срок жизни - 1 час
    "iat": datetime.now(timezone.utc) # Время создания
}
token = jwt.encode(payload, SECRET_KEY, algorithm="HS256")

# 2. Проверка токена при каждом запросе
try:
    decoded_payload = jwt.decode(token, SECRET_KEY, algorithms=["HS256"])
    print("Токен валиден. User ID:", decoded_payload['sub'])
except jwt.ExpiredSignatureError:
    print("Ошибка: срок действия токена истек.")
except jwt.InvalidTokenError:
    print("Ошибка: невалидный токен.")

Ключевые аспекты безопасности:

  • HTTPS обязателен, чтобы предотвратить перехват токена.
  • Не храните чувствительные данные в payload, так как он легко декодируется (Base64).
  • Используйте короткий срок жизни токенов (exp) и реализуйте механизм их обновления (refresh tokens).