Microservice: Базовый авторизационный сервис, токен доступа, токен обновления

Спецификация gRPC-интерфейсов, логики авторизации и архитектуры хранения данных

Published

June 11, 2026

WarningОграничение публичной документации

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

  • Полная спецификация метода: Будет доступна только во внутреннем контуре разработки (Confluence).

1 Общее назначение и архитектурная роль сервиса

Базовый микросервис Auth-Service выполняет функции единого центра аутентификации, ведения активных сессий и авторизации межсервисных запросов в системе. Компонент реализован как gRPC-сервер на языке Go.

1.1 Ключевые архитектурные решения:

  • Оптимизация межсервисного взаимодействия: Идентификатор группы пользователя (group_id), к которой он привязан, извлекается при авторизации и вшивается в MapClaims JWT-токена подписи HMAC-SHA256. Это исключает необходимость для смежных доменных воркеров выполнять повторные SQL-запросы в базу авторизации — они получают контекст группы напрямую из валидированной структуры токена.
  • Сквозная трассировка (Distributed Tracing): Транспортный слой оснащен перехватчиком UnaryServerInterceptor, который автоматически проверяет наличие заголовка x-request-id в gRPC-метаданных. Если клиент или прокси-сервер не передали маркер, интерцептор генерирует UUID v4, регистрирует его в контексте и обогащает им каждую строку структурированного JSON-лога в os.Stdout.

2 Структура и конфигурация слоя баз данных (Реестр СУБД)

Компонент инициализации инфраструктуры DB обеспечивает параллельное подключение к реляционному пулу PostgreSQL и кэш-слою Redis с обязательным синхронным вызовом процедуры Ping() при старте.

2.1 Конфигурация пула соединений PostgreSQL (pgx/v5)

Для минимизации накладных расходов на сетевые транзакции используется пул соединений драйвера pgxpool. Настройки пула зафиксированы в коде: * MaxConns — Максимальный лимит одновременно открытых сессий пула равен 25. * MinConns — Минимальное количество гарантированно удерживаемых коннектов равно 5. * MaxConnLifetime — Предельный жизненный цикл сетевого соединения составляет 30 минут, после чего оно переоткрывается.

2.2 Конфигурация сессионного кэша Redis (go-redis/v9)

Репозиторий SessionRepository изолирует хранение временных долгоживущих токенов в оперативной памяти Redis на логическом секторе DB 0. Ключи формируются по маске refresh:UUID_ТОКЕНА со строгим ограничением времени жизни (TTL), равным 30 дням (30 * 24 * Hour). При выходе из системы или ротации ключей запись атомарно уничтожается методом DeleteSession.

2.3 ER-диаграмма базы данных (Связи сущностей)

%%{init: {
  'theme': 'base', 
  'er': {
    'useMaxWidth': false
  },
  'themeVariables': {
    'mainBkg': '#FFF9C4',
    'lineColor': '#2C3E50',
    'borderClassName': '#FBC02D',
    'nodeBorder': '#FBC02D',
    'attributeBackend': '#FFF9C4'
  }
}}%%

erDiagram
    users_postgres {
        int64 id PK
        varchar email UK
        varchar password_hash
        varchar user_type
        uuid group_id
        boolean is_active
        timestamp created_at
        timestamp updated_at
    }

    sessions_redis {
        string key_token_uuid PK
        int64 user_id
    }

    users_postgres ||--o{ sessions_redis : "has active"
    


3 Спецификация gRPC-интерфейсов (Транспортный контракт)

Сервер обрабатывает данные в рамках спецификации AuthServiceServer, преобразуя внутренние исключения репозиториев в канонические коды ошибок google.golang.org/grpc/codes.

3.1 Метод ValidateToken (Авторизация токена доступа)

Вызывается шлюзами интеграции для подтверждения прав клиента.

  • Входные параметры (pb.ValidateRequest): Строковое поле access_token. При пустом значении сервер возвращает статус codes.InvalidArgument.
  • Выходные параметры (pb.ValidateResponse): Логический флаг is_valid, числовой идентификатор пользователя user_id, строковые метки типа аккаунта user_type (Строго фиксированные доменные константы: REAL или DIGITAL) и UUID-строка group_id. При невалидной криптографической подписи или истечении срока действия токена отдается статус codes.Unauthenticated.

4 Сценарий взаимодействия при валидации сессии (Sequence Diagram)

Ниже представлена диаграмма обработки запроса верификации токена, разбора метаданных трассировки и логического маппинга параметров группы.

%%{init: {
  'theme': 'base',
  'themeVariables': {
    'actorBkg': '#E3F2FD',
    'actorBorder': '#546E7A',
    'actorTextColor': '#0D47A1',
    'rectBkg': '#FFF9C4',
    'rectBorder': '#FBC02D',
    'noteBkgColor': '#F3E5F5',
    'noteBorderColor': '#7E57C2',
    'noteTextColor': '#311B92',
    'signalColor': '#2C3E50',
    'signalLineColor': '#2C3E50'
  }
}}%%
sequenceDiagram
    autonumber
    actor Client as Внешний gRPC Компонент
    participant Interceptor as LoggingInterceptor (Go)
    participant Server as GRPCServer Transport
    participant UR as UserRepository (Postgres)

    Client->>Interceptor: Вызов метода gRPC ValidateToken с MD [x-request-id]
    activate Interceptor
    
    note over Interceptor: Шаг 2: Извлечение x-request-id из метаданных.<br/>При отсутствии — генерация uuid.New().String()
    note over Interceptor: Шаг 3: Инициализация JSON-логгера slog с фиксацией request_id
    
    Interceptor->>Server: Перенаправление запроса во внутренний транспортный хэндлер
    activate Server
    
    Server->>UR: Вызов репозитория пользователей по ID из токена GetByID(id)
    activate UR
    UR-->>Server: Возврат User (ID, UserType, IsActive, GroupID)
    deactivate UR

    note over Server: Шаг 7: Проверка активности IsActive и маппинг GroupID в наружное поле GroupId
    
    Server-->>Interceptor: Проброс protobuf-структуры ValidateResponse и статуса ошибки
    deactivate Server
    
    note over Interceptor: Шаг 9: Расчет duration_ms и запись лога JSON Lines в os.Stdout
    
    Interceptor-->>Client: Ответ ValidateResponse + gRPC Status Code
    deactivate Interceptor

4.1 Таблица расшифровки шагов сценария ValidateToken

Шаг Действие Параметры / Запросы / DTO Код ошибки (canonical_code) HTTP / gRPC статус
1 (Client -> Interceptor) Смежный микросервис выполняет вызов метода проверки сессии, передавая маркер трассировки в метаданных gRPC. gRPC Metadata Context:
x-request-id: "uuid-v4-trace-id"
AUTH_INVALID_ARGUMENT codes.InvalidArgument (400)
2 (Interceptor -> Interceptor) Внутренняя логика: Интерцептор извлекает маркер из контекста. При его отсутствии генерирует новый UUID и регистрирует его в контексте под ключом RequestIDKey. Внутренняя функция:
getOrCreateRequestID(ctx)
Нет codes.OK (200)
3 (Interceptor -> Interceptor) Внутренняя логика: В поток os.Stdout сбрасывается JSON-лог о начале обработки запроса с привязанным идентификатором трассировки. slog JSON Line Payload:
{ "msg": "gRPC request started", "request_id": "uuid", "method": "/pb.AuthService/ValidateToken" }
Нет codes.OK (200)
4 (Interceptor -> Server) Интерцептор передает управление на транспортный слой gRPC-сервера, пробрасывая модифицированный контекст. Внутренний вызов Go:
handler(ctx, req)
Нет codes.OK (200)
5 (Server -> UR) Сервис проверяет подпись входящего токена через jwt.Parse и выполняет запрос к репозиторию для извлечения актуальной карточки по ID. Внутренний метод репозитория:
r.pool.QueryRow(ctx, query, id).Scan(...)
DB_CONNECTION_FAILURE codes.Internal (500)
6 (UR -> Server) Репозиторий перехватывает ошибку отсутствия строк pgx.ErrNoRows, трансформирует ее в доменное исключение и возвращает данные. SQL Response:
Кортеж полей (id, email, password_hash, user_type, is_active, group_id)
AUTH_USER_NOT_FOUND codes.Unauthenticated (401)
7 (Server -> Server) Внутренняя логика: Транспортный слой проверяет флаг блокировки аккаунта user.IsActive и осуществляет финальный маппинг данных в структуру ответа. Protobuf Response Message:
pb.ValidateResponse{GroupId: groupID, IsValid: true}
AUTH_ACCOUNT_SUSPENDED codes.Unauthenticated (401)
8 (Server -> Interceptor) gRPC-сервер возвращает сформированный protobuf-ответ обратно в слой интерцептора логирования. gRPC Internal Response Нет codes.OK (200)
9 (Interceptor -> Interceptor) Внутренняя логика: Фиксация общего времени обработки запроса. Запись итогового лога в JSON-формате в stdout. slog JSON Line Payload:
{ "level": "INFO", "duration_ms": 11.4, "request_id": "trace-id" }
CRYPTO_SIGNING_ERROR codes.Internal (500)
10 (Interceptor -> Client) Финальный ответ со статусом проверки и идентификатором группы группы уходит вызывающей доменной системе. gRPC Wire Response DTO:
ValidateResponse{is_valid: true, group_id: "uuid"}
Нет codes.OK (200)

5 Справочник Обсервабилити (Структура логов slog для ClickHouse)

Каждое событие, проходящее через интерцептор, пишется в os.Stdout в виде плоской JSON-строки. При обработке ошибок Vector отправляет в ClickHouse следующий набор канонических полей:

1. Код (canonical_code) 2. Уровень (log_level) 3. Статусы (transport_statuses) 4. Получатель (error_target) 5. JSON для Фронтенда (ui_payload) 6. Метрики для ClickHouse (observability_json)
AUTH_INVALID_ARGUMENT WARN {“grpc”: 3, “http”: 400} EXTERNAL_SYSTEM null {“metric”: “validation_fail”, “labels”: {“reason”: “missing_token_or_email”}}
AUTH_TOKEN_EXPIRED WARN {“grpc”: 16, “http”: 401} EXTERNAL_SYSTEM null {“metric”: “auth_fail”, “labels”: {“reason”: “invalid_token_signature_or_expired”}}
AUTH_ACCOUNT_SUSPENDED WARN {“grpc”: 7, “http”: 403} EXTERNAL_SYSTEM null {“metric”: “login_blocked”, “labels”: {“reason”: “user_is_blocked”}}
DB_CONNECTION_FAILURE ERROR {“grpc”: 13, “http”: 500} INTERNAL_SYSTEM null {“metric”: “db_pool_error”, “labels”: {“service”: “auth_service”}}