0.2.3 • Published 4 years ago

modules-monorepo v0.2.3

Weekly downloads
-
License
ISC
Repository
-
Last release
4 years ago

Модуль авторизации

Общие сведения.


Репозиторий содержит 4 пакета: 1. @libs/security - библиотека для работы с jwt и csrf токенами. 2. @skeleton/common - пакет для общего функционала, используемого в других skeleton-модулях. (планируется в будущем вынести в отдельный репозиторий)

  1. @skeleton/auth - framework agnostic модуль авторизации (подключается к express, как middleware).
  2. @skeleton/auth-nest - модуль для nestjs, оборачивающий функционал @skeleton/auth.

demo-auth и demo-auth-nest - тестовые с подключенными модулями авторизации (на чистом экспресс и на nestjs соотвественно)


Порядок развёртывания репозитория.


  1. Для комфортной работы с репозиторием установите глобально пакеты @nestjs/cli и ts-node.
  2. Склонируйте репозиторий.
  3. Из корня репозитория выполняем последовательно:
npm install
npm run bootsrap #поздаёт симлинки между пакетами, т. к. они зависят друга)
npm run build
  1. В папках demo-auth и demo-auth-nest создайте копии .example.env c названием .env

  2. В случае, если у вас локально установлен REDIS в файлах .env установите параметры подключения (SESSREDIS*) к нему. Если не установлен - два варианта: а) поставьте :-) б) разверните редис в контейнере (см. скрипты в sess_redis);

  3. Для проверки корректности развёртывания выполните:

npm run test # из корня проекта.

Если все тесты пройдены.. отлично )

  1. Для запуска сервисов с модулем авторизации, требуется поднятый сервер аутентификации (тесты поднимают его автоматически). Чтобы просто запустить сервис для отладки, можно поднять моковый сервер аутентификации:
npm run tools:mock-server
# Сервис ищёт файл api-mock.config.js, в котором указано, что и в каких случаях надо возвращать.

Публикация пакетов.


Подготовка.

Для работы с пакетами @skeleton/* и @libs/* (как для скачивания, так и для публикации) необходимо настроить npm:

npm config set @skeleton:registry http://host:port
npm config set @libs:registry http://host:port

npm login --registry http://host:port

На сегодняшний день в качестве registry используется: http://nexus.infra.medpoint24.lo/repository/medpoint24_npm/

Публикация.

Изначально для публикации пакетов использовалась lerna (команда npm run pub из корня репозитория). Но лерна при публикации делает некоторые не совсем очевидные вещи (добавляет теги, делает git push и т. п.), что не всегда удобно.

Поэтому на данный момент пакеты публикуются при помощи

npm publish # из папки пакета

Стремимся к CI. То есть публикация пакетов будет происходить при пуше в мастер.


API


Оба demo-сервиса имеют идентичное api:

GET /user (требуется разрешение: 'VIEW_USER')

POST /user (требуется разрешение: 'CREATE_USER')

DELETE /user (требуются разрешения: 'DELETE_USER' И 'VIEW_USER')

POST /drop/db (требуются разрешения: 'ADMIN' ИЛИ 'SUPERADMIN')

GET /ignored (разрешения не требуется, как и авторизация вообще)

Все методы не требует параметров и при успешной авторизации возвращают 200 true.


Описание системы.


Авторизация пользователя проходит в два этапа: 1. Валидация jwt и csrf токенов (на каждый запрос). 2. Проверка прав доступа (права устанавливаются на каждый роут отдельно).

Порядок действий следующий:

  • Для получения доступа клиент должен в заголовке Authorization приложить jwt-токен, полученный у сервера аутентификации. Authorization: Bearer df3gf....
# Для создания тестового токена можно воспользоваться утилитой:
npm run tools:jwt
# Выведет валидный токен в консоль.
  • Модуль авторизации хэширует токен и по хэшу пытается найти сохранённые данные в REDIS. Если на сервис уже приходили с данным токеном, расшиврованные данные из него, а также права пользователя уже хранятся в REDIS. Если нет - запускается полная процедура (см. ниже)

  • В случае, если сессия в REDIS не найдена, jwt-токен валидируется и расшифровывается. Затем отправляется запрос на сервер аутентификации для получения прав. Права (permissions) пользователя представляют из себя массив строк вида: 'CREATE_USER', 'UPDATE_USER'. Полученные права используются для получения доступа к конкретному роуту.

    ВАЖНО! При успешной авторизации, в каждом ответе модуль прикладывает csrf-токен (в заголовке X-Csrf-Token). Его необходимо приложить в таком же заголовке к следующему запросу. ПЕРЕГЕНЕРИРУЕТСЯ ПРИ КАЖДОМ ЗАПРОСЕ

  • Если сессия в REDIS найдена, проверяется не истёк ли срок действия токена, а также валидируется csrf-токен. Если всё ОК, пропускаем дальше на этап проверки прав доступа.

  • Права доступа устанавливаются на каждый роут отдельно. Если указывается несколько, то по умолчанию будет проверяться наличие ВСЕХ (это можно изменить дополнительным параметром) - см. demo-сервисы.

  • В случае неудачной попытки доступа клиенту возвращаются код ошибки.

Дополнительные параметры

Настройки модуля авторизации берутся из .env файлов. За что отвечают конкретные значения - написано в комментариях.

Следуюет отметить следующии возможности:

  • Для печати в консоль всех логов модуля авторизации установите LOGLEVEL=_verbose
  • Чтобы клиенту кроме кода ошибки возвращалось также описание, установите VERBOSEERRORS=_true
  • Для роутов перечисленных через запятую в параметре IGNORE_ROUTES авторизация будет полностью пропущена. ВАЖНО! Если указать '/public', будут открыты все роуты, содержащие данную подстроку.
  • Авторизация может быть полностью отключена (в тестовых целях) путём установки параметра DISABLEAUTH=_true В этом случае, каждый запрос получит разрешения перечисленные через запятую в параметре TEST_PERMISSIONS
  • Все запросы с ошибками 401 и 403 будут возвращаться клиенту с задержкой указанной в параметре AUTH_ERRORS_DELAY (в миллисекундах)

Сценарии:

    Incorrect Jwt.
      STATE: any
        ✓ should return 401 if JWT is missing.
        ✓ should return 401 if JWT signature is incorrect.
        1) should return 401 if JWT is expired
        ✓ should return 401 if JWT payload can`t be parsed (109ms)
    Correct Jwt.
      STATE: no session.
        X-Csrf-Token header exists.
          ✓ should return 401 if Csrf token EXISTS. (125ms)
        X-Csrf-Token header NOT exists.
          State: auth-server UNREACHABLE
            ✓ should return 500
          STATE: auth-server returns 401
            ✓ should return 401
          STATE: auth-server provides SUFFICIENT permissions
            ✓ should return 200
          STATE: auth-server provides INSUFFICIENT permissions
            ✓ should return 403 (107ms)
      STATE: session exists.
        Csrf valid.
          STATE: SUFFICIENT permissions
            ✓ should return 200
          STATE: INSUFFICIENT permissions
            ✓ should return 403 (224ms)
        Csrf invalid.
          ✓ should return 401 if Csrf is MISSING (132ms)
          ✓ should return 401 if Csrf is WRONG (133ms)

В табличном виде: XWIKI


TODO:


  • Валидация схемы сonfig'a (чтобы пустые значения нельзя было ввести в обязательные поля)
  • Интеграционные тесты для demo-приложений
  • Выделить mock-server в отдельную тулзу @tools/mock-server? (Возможно, завести отдельный репозиторий для тулзов)
  • Инструкции в README файлах.
  • Обсудить с Игорем и утвердить (при необходимости - исправить) формат ответов в случае различных ошибок.
  • В случае обращения с протухшим токеном или обнаружения протухшей сессии возвращать 444.
  • Проверить, заходит ли программа вообще в логику удаления сессии, по видимому нет - нужно исправить. Или вообще удалить - обсудить с Рустом.
  • Сделать тесты для demo-auth-nest
  • Решить, что делает nestjs модуль при ошибках авторизации - выкидывает HttpException, как сейчас или что-то другое?
  • Авторизация при соединении через Web Socket?
  • Документация кода (кроме demo-) - apiDoc
  • Ревью работы с исключениями (свежий взгляд).
  • Протестировать подключение в отсутствии Redis и с отключенной авторизацией. (скорее всего работать не будет) - ИСПРАВЛЕНО
  • Добавить валидацию Identity и IJwt (class-validator)