Перейти к содержанию

05 security layers

Семь слоёв безопасности: от TLS до PIN на устройстве.

Слои безопасности

flowchart TD
    L7[L7: PIN + Biometric\nFlutter app] -.->|защищает доступ к| L1
    L1[L1: TLS\nnginx public ingress] --> L2[L2: JWT Verification\nServerpod Auth middleware]
    L2 --> L3[L3: AccountType Guard\nrequireAccountType]
    L3 --> L4[Бизнес-логика endpoint]
    L4 --> L5[L5: PII Encryption\nAES-256-GCM]
    L4 --> L6[L6: HMAC Signing\nPspHmacClient → PM]
    L8[L8: nginx auth_request\n/nginx/auth → PM] -.->|проверяет JWT для| L1

Таблица слоёв

Слой Технология Файл Защищает
L1: TLS nginx SSL termination nginx.conf (infra) Шифрование трафика клиент ↔ сервер
L2: JWT Serverpod built-in auth middleware Serverpod framework Аутентификация каждого запроса; accessToken 30 мин, refreshToken 14 дней
L3: AccountType Guard requireAccountType(session, ['wallet'\|'merchant'\|'agent']) lib/src/endpoints/kyc_endpoint.dart, merchant_endpoint.dart Разграничение доступа приложений (wallet / merchant / agent)
L4: Status Guard auth_validate_endpoint.dart — блокировка blocked, registration_expired lib/src/endpoints/auth/auth_validate_endpoint.dart Запрет доступа для заблокированных и истёкших аккаунтов
L5: PII Encryption AES-256-GCM lib/src/services/pii/pii_crypto_service.dart Персональные данные в БД (имя, документ, адрес)
L6: HMAC Signing HMAC-SHA256 canonical string lib/src/services/payment/psp_hmac_client.dart Каждый запрос Auth Center → Payment Manager
L7: PIN + Biometric 6-значный PIN + биометрия Flutter Flutter apps (NatBank requirement) Доступ к приложению на устройстве; auto-lock 5 мин
L8: nginx auth_request Проксирование /api/pm/* через /nginx/auth nginx.conf (infra) JWT-верификация для PM-прокси без участия Auth Center endpoint

PII Encryption

Blob layout (lib/src/services/pii/pii_crypto_service.dart, строка 9):

[1 byte version=0x01][12 bytes nonce][ciphertext][16 bytes GCM tag]
Параметр Значение Источник
Алгоритм AES-256-GCM dart:cryptography / cryptography package
Ключ 32 байта из base64 passwords.yamlpiiEncryptionKey
Nonce 12 байт, случайный на каждый encrypt Генерируется SecretBox
GCM tag 16 байт, appended в конец Встроен в SecretBox
Phone hash pepper HMAC-SHA256 pepper passwords.yamlpiiPhoneHashPepper
NationalId hash pepper HMAC-SHA256 pepper passwords.yamlpiiNatIdHashPepper

Peppers читаются в PiiHashService.fromServerpod() из passwords.yaml или env vars
(SERVERPOD_PASSWORD_piiPhoneHashPepper / SERVERPOD_PASSWORD_piiNatIdHashPepper).
Файл: lib/src/services/pii/pii_hash_service.dart

HMAC к PM

Canonical string format (закреплён тестами, синхронизирован с payment-manager/src/auth/hmac.ts):

${timestampSeconds}\n${METHOD}\n${path}\n${sha256hex(body)}

Четыре заголовка каждого запроса:

Заголовок Значение
X-Service-Id Идентификатор сервиса (из passwords.yaml)
X-Timestamp Unix timestamp секунды (строка)
X-Signature Lowercase hex HMAC-SHA256 над canonical string
X-User-Id userId пользователя из сессии

Файл: lib/src/services/payment/psp_hmac_client.dart, строки 82–127

JWT конфиг

Настройки в lib/server.dart:

Параметр Значение Примечание
accessTokenLifetime 30 минут Выше дефолта Serverpod (10 мин) — буфер для мобильных сетей
refreshTokenLifetime 14 дней (Serverpod default) Ротируется автоматически
Launch JWT алгоритм RS256 (RSA + SHA-256) Для mini-app интеграций
Launch JWT TTL 5 минут const _ttl = Duration(minutes: 5)
Launch JWT issuer auth.onewallet
Launch JWT audience miniapp-специфичный slug Передаётся при вызове LaunchJwtService.sign()

Launch JWT подписывается приватным RSA-ключом из passwords.yamljwtLaunchRsaPrivateKeyPem.
JWKS (публичный ключ) доступен через GET /.well-known/jwks.json (route JwksRoute).
Файл: lib/src/services/auth/launch_jwt_service.dart