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):
| Параметр | Значение | Источник |
|---|---|---|
| Алгоритм | AES-256-GCM | dart:cryptography / cryptography package |
| Ключ | 32 байта из base64 | passwords.yaml → piiEncryptionKey |
| Nonce | 12 байт, случайный на каждый encrypt | Генерируется SecretBox |
| GCM tag | 16 байт, appended в конец | Встроен в SecretBox |
| Phone hash pepper | HMAC-SHA256 pepper | passwords.yaml → piiPhoneHashPepper |
| NationalId hash pepper | HMAC-SHA256 pepper | passwords.yaml → piiNatIdHashPepper |
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):
Четыре заголовка каждого запроса:
| Заголовок | Значение |
|---|---|
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.yaml → jwtLaunchRsaPrivateKeyPem.
JWKS (публичный ключ) доступен через GET /.well-known/jwks.json (route JwksRoute).
Файл: lib/src/services/auth/launch_jwt_service.dart