Categorygithub.com/Dimortilus/test-task-backdev
modulepackage
0.0.0-20240313195550-9017ad22b4f5
Repository: https://github.com/dimortilus/test-task-backdev.git
Documentation: pkg.go.dev

# README

Test task BackDev

Тестовое задание на позицию Junior Backend Developer

Используемые технологии:

  • Go
  • JWT
  • MongoDB

Задание:

Написать часть сервиса аутентификации.
Два REST маршрута:

  • Первый маршрут выдает пару Access, Refresh токенов для пользователя с идентификатором (GUID) указанным в параметре запроса
  • Второй маршрут выполняет Refresh операцию на пару Access, Refresh токенов

Требования:

Access токен тип JWT, алгоритм SHA512, хранить в базе строго запрещено.
Refresh токен тип произвольный, формат передачи base64, хранится в базе исключительно в виде bcrypt хеша, должен быть защищен от изменения настороне клиента и попыток повторного использования.
Access, Refresh токены обоюдно связаны, Refresh операцию для Access токена можно выполнить только тем Refresh токеном который был выдан вместе с ним.

Описание решения:

  • Формат Refresh токена: случайная последовательность из 32 байт.
    Для каждого токена генерируется новая последовательность.
    Такой тип токенов, судя по всему, называется "opaque token", или "reference token".
  • На клиенте оба типа токенов хранятся в httpOnly cookies.
  • Схема "один пользователь - один Refresh токен".
    В Mongo хранится документ со следующими полями:
    - GUID
    - bcrypt хеш Refresh токена
    - "exp", время истечения срока годности (Unix timestamp)
    - bcrypt хеш (раскодированной из base64rawURL) сигнатуры Access токена
    Хранить GUID необходимо для возможности досрочного отзыва Refresh токена конкретного пользователя.
    Хранить exp (expirtaion time) необходимо для проверки Refresh токена на предмет истечения срока годности.
  • Хранить bcrypt хеш подписи Access токена необходимо для проверки связи предъявляемой пары Access и Refresh токенов. Длина раскодированной из base64rawURL подписи JWT токена с использованием алгоритма HMACSHA512 составляет 64 байта, что позволяет применять к ней bcrypt хеширование. Максимальная длина пароля которую принимает функция bcrypt.GenerateFromPassword() составляет 72 байта.
  • POST запрос по маршруту /generate-tokens.
    Сервер извлекает GUID из JSON тела запроса.
    1. Генерирует новую пару Access-Refresh токенов.
    2. Выполняет upsert документа по GUID в Mongo.
    3. Кодирует Refresh токен в base64.
    4. Сохраняет токены в cookies пользователя.
  • POST запрос по маршруту /refresh-tokens.
    Сервер извлекает GUID из JSON тела запроса.
    Ищет в Mongo документ по GUID.
    Если документ НЕ найден, отказывает в выдаче токенов.
    Если документ найден:
    - Извлекает из cookies Access токен.
    - Валидирует Access токен (подпись, срок годности).
    - Проверяет Access токен, проверяя его подпись её bcrypt хешем из документа.
    - Извлекает из cookies Refresh токен, декодирует из base64.
    - Проверяет Refresh токен его bcrypt хешем из документа.
    - Проверяет не истёк ли у Refresh токена срок годности.
    Если валидация токенов прошла успешно:
    1. Генерирует новую пару Access-Refresh токенов.
    2. Выполняет upsert документа по GUID в Mongo.
    3. Кодирует Refresh токен в base64.
    4. Сохраняет токены в cookies пользователя.
  • POST запрос по маршруту /test-access-token.
    Сервер извлекает Access токен из cookies, выполняет парсинг и валидацию токена (подпись, срок годности).
  • POST запрос по маршруту /replace-token-cookie.
    Сервер выполняет в cookie подмену текущего Access или Refresh токена на переданный в JSON запроса. Поле JSON запроса для токена, который требуется оставить прежним, заполнено пустой строкой. Используется для тестирования связности Access и Refresh токенов во время Refresh операции.
  • Переменная ACCESS_TOKEN_SECRET в .env файле заполнена тестовым ключом в виде HEX-строки.
    В соответствии с рекомендациями, длина ключа для алгоритма SHA512 составляет 1024 бит.