kabiroman / octawire-auth-service-php-client-bundle
Symfony Bundle for Octawire Auth Service
Installs: 1
Dependents: 0
Suggesters: 0
Security: 0
Stars: 0
Watchers: 0
Forks: 0
Open Issues: 0
Type:symfony-bundle
pkg:composer/kabiroman/octawire-auth-service-php-client-bundle
Requires
- php: ^8.1
- firebase/php-jwt: ^6.0
- kabiroman/octawire-auth-service-php-client: ^0.9.4
- symfony/config: ^6.4|^7.0
- symfony/dependency-injection: ^6.4|^7.0
- symfony/http-kernel: ^6.4|^7.0
- symfony/security-core: ^6.4|^7.0
- symfony/security-http: ^6.4|^7.0
Requires (Dev)
- phpunit/phpunit: ^10.5
- symfony/framework-bundle: ^6.4|^7.0
- symfony/routing: ^6.4|^7.0
- symfony/security-bundle: ^6.4|^7.0
- symfony/yaml: ^6.4|^7.0
This package is auto-updated.
Last update: 2025-12-01 19:04:11 UTC
README
Symfony Bundle для интеграции PHP клиента Octawire Auth Service с Symfony Security Component.
Требования
- PHP 8.1+
- Symfony 6.4+ / 7.0+
kabiroman/octawire-auth-service-php-client^0.9.4ext-sockets(для TCP соединений)ext-json(для JSON обработки)
Важно: Bundle использует TCP/JATP транспорт (Protocol v1.0), не требует gRPC extension.
Установка
composer require kabiroman/octawire-auth-service-php-client-bundle
📖 Подробное руководство: Для детальных инструкций по установке и настройке для различных сценариев использования см. INSTALLATION.md
Конфигурация
1. Зарегистрируйте Bundle
В config/bundles.php:
return [ // ... Kabiroman\Octawire\AuthService\Bundle\OctawireAuthBundle::class => ['all' => true], ];
2. Настройте Bundle
Создайте файл config/packages/octawire_auth.yaml:
octawire_auth: # Значения default_project и project_id — это UUID проектов, заданные в конфигурации Auth Service default_project: '018fd6d2-8bda-7c61-b01d-12d6eddb02af' projects: 018fd6d2-8bda-7c61-b01d-12d6eddb02af: transport: 'tcp' tcp: host: 'localhost' port: 50052 # TCP/JATP порт (по умолчанию 50052) persistent: true # Переиспользование соединений tls: enabled: false # true для production # ca_file: '%kernel.project_dir%/config/tls/ca.crt' # cert_file: '%kernel.project_dir%/config/tls/client.crt' # для mTLS # key_file: '%kernel.project_dir%/config/tls/client.key' # для mTLS project_id: '018fd6d2-8bda-7c61-b01d-12d6eddb02af' api_key: '%env(AUTH_API_KEY)%' retry: max_attempts: 3 key_cache: driver: 'memory' ttl: 3600 018fd6d2-91da-7c77-b40d-abcdef012345: transport: 'tcp' tcp: host: 'auth.example.com' port: 50052 persistent: true tls: enabled: true ca_file: '%kernel.project_dir%/config/tls/ca.crt' server_name: 'auth.example.com' project_id: '018fd6d2-91da-7c77-b40d-abcdef012345' service_auth: service_name: 'api-gateway' service_secret: '%env(AUTH_SERVICE_SECRET)%'
3. Настройте Security
В config/packages/security.yaml:
security: firewalls: api: pattern: ^/api/ stateless: true custom_authenticators: - octawire_auth.authenticator access_control: - { path: ^/api/, roles: ROLE_USER }
Использование
Автоматическая валидация токенов
Bundle автоматически валидирует JWT токены из заголовка Authorization: Bearer <token> для всех запросов, соответствующих паттерну firewall.
Валидация происходит через TCP/JATP соединение с Auth Service, используя метод ValidateToken.
Доступ к пользователю в контроллерах
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\Security\Http\Attribute\IsGranted; use Kabiroman\Octawire\AuthService\Bundle\Security\OctowireUser; use Kabiroman\Octawire\AuthService\Bundle\Security\OctowireToken; class ApiController extends AbstractController { #[IsGranted('ROLE_USER')] public function index(): JsonResponse { $user = $this->getUser(); if ($user instanceof OctowireUser) { $userId = $user->getUserId(); $claims = $user->getClaims(); $role = $user->getClaim('role'); } return $this->json(['user' => $userId]); } }
Доступ к токену
use Kabiroman\Octawire\AuthService\Bundle\Security\OctowireToken; // В контроллере $token = $this->getToken(); if ($token instanceof OctowireToken) { $jwtToken = $token->getJwtToken(); $projectId = $token->getProjectId(); $claims = $token->getClaims(); }
Работа с несколькими проектами
Bundle поддерживает работу с несколькими проектами. Project ID может быть:
- Извлечен из токена (из claims)
- Указан в конфигурации как
default_project - Определен динамически на основе токена
Концепция project_id
Важно: project_id используется для разделения разных типов токенов и алгоритмов подписи.
Архитектурная концепция
- Разные типы токенов: Разные
project_idмогут использовать разные алгоритмы подписи (RS256, ES256, HS256 и т.д.) - Whitelist подход: Каждый сервис настраивается на работу только с определенными
project_id(whitelist) - Безопасность: Токены с
project_id, не указанным в конфигурации, автоматически отклоняются до валидации - Контроль доступа: Это позволяет контролировать, какие типы токенов сервис принимает
Пример использования
octawire_auth: default_project: '018fd6d2-8bda-7c61-b01d-12d6eddb02af' # Проект по умолчанию (UUID) projects: 018fd6d2-8bda-7c61-b01d-12d6eddb02af: # Токены для API v1 (RS256) transport: 'tcp' tcp: host: 'auth.example.com' port: 50052 project_id: '018fd6d2-8bda-7c61-b01d-12d6eddb02af' key_cache: driver: 'memory' ttl: 3600 018fd6d2-91da-7c77-b40d-abcdef012345: # Токены для API v2 (ES256) transport: 'tcp' tcp: host: 'auth.example.com' port: 50052 project_id: '018fd6d2-91da-7c77-b40d-abcdef012345' key_cache: driver: 'memory' ttl: 3600 018fd6d2-9acd-7d71-bf1d-fedcba987654: # Внутренние токены (HS256) transport: 'tcp' tcp: host: 'auth-internal.example.com' port: 50052 project_id: '018fd6d2-9acd-7d71-bf1d-fedcba987654' key_cache: driver: 'redis' ttl: 3600
Поведение:
- Сервис будет принимать токены только с перечисленными UUID
- Токены с другими
project_idбудут отклонены с ошибкой:Token project ID "..." - Если токен не содержит
project_idв claims, используетсяdefault_project - Если токен не содержит
project_idиdefault_projectне настроен, токен будет отклонен
Логика выбора project_id
- Из токена: Если токен содержит
project_idв claims (илиaud), используется он - Whitelist проверка: Проверяется, что
project_idиз токена присутствует в конфигурации - Default fallback: Если
project_idне найден в токене, используетсяdefault_project - Ошибка: Если
project_idне найден в токене иdefault_projectне настроен, токен отклоняется
Режимы валидации токенов
Bundle поддерживает три режима валидации токенов:
Режим 1: Remote Validation (по умолчанию)
Полная валидация через Auth Service:
- ✅ Проверка blacklist
- ✅ Полная валидация всех аспектов токена
- ✅ Централизованное управление
- ⚠️ Зависимость от доступности Auth Service
- ⚠️ Сетевая задержка на каждый запрос
Конфигурация:
octawire_auth: validation_mode: 'remote' # По умолчанию check_blacklist: true # ...
Режим 2: Local Validation
Локальная проверка подписи с использованием публичных ключей:
- ✅ Независимость от доступности Auth Service
- ✅ Низкая задержка (нет сетевых запросов)
- ✅ Меньше нагрузки на Auth Service
- ⚠️ Не проверяет blacklist (требует отдельной проверки или пропуска)
- ⚠️ Требует синхронизации публичных ключей
Конфигурация:
octawire_auth: validation_mode: 'local' check_blacklist: false # Не используется в local режиме # ...
Режим 3: Hybrid Validation
Локальная проверка подписи + удаленная проверка blacklist:
- ✅ Компромисс между производительностью и безопасностью
- ✅ Локальная проверка подписи + удаленная проверка blacklist
- ⚠️ Требует доступности Auth Service для проверки blacklist
Конфигурация:
octawire_auth: validation_mode: 'hybrid' check_blacklist: true # Проверка blacklist через Auth Service # ...
Рекомендации:
- Gateway Service: Hybrid режим для максимальной производительности + проверка blacklist
- Другие сервисы: Remote режим для простоты
- High-load окружения: Local режим для независимости от Auth Service
Использование AuthClient напрямую
use Kabiroman\Octawire\AuthService\Bundle\Factory\AuthClientFactory; use Kabiroman\Octawire\AuthService\Client\Request\JWT\IssueTokenRequest; class MyService { public function __construct( private AuthClientFactory $clientFactory ) {} public function issueToken(string $userId, string $projectId): string { $client = $this->clientFactory->getClient($projectId); // v0.9.4+: используйте DTO с именованными параметрами $request = new IssueTokenRequest( userId: $userId, projectId: $projectId, claims: ['role' => 'admin'], accessTokenTtl: 3600, refreshTokenTtl: 86400 ); $response = $client->issueToken($request); // v0.9.4: expiresIn (секунды) вместо accessTokenExpiresAt (timestamp) return $response->accessToken; } }
Конфигурация проектов
Каждый проект может иметь следующие настройки:
transport(опционально, по умолчанию 'tcp') - транспорт ('tcp' для TCP/JATP)tcp(обязательно для TCP транспорта) - конфигурация TCP соединенияhost(обязательно) - хост TCP сервераport(обязательно) - порт TCP сервера (по умолчанию 50052)persistent(опционально, по умолчанию true) - использовать persistent соединения
project_id(обязательно) - UUID проекта, выданный Auth Serviceservice_auth(опционально) - параметры межсервисной аутентификации:service_name— имя сервиса (должно совпадать с whitelist на Auth Service)service_secret— секрет сервиса, используемый для выдачи service-token
api_key(опционально) - API ключ для аутентификацииtcp.tls- настройки TLS/mTLS для TCP соединенияenabled- включить TLS (обязательно для production)required- требовать TLS (не подключится если TLS недоступен)cert_file- путь к сертификату клиента (для mTLS)key_file- путь к приватному ключу (для mTLS)ca_file- путь к CA сертификатуserver_name- имя сервера для проверки TLS (SNI)
retry- настройки повторных попытокmax_attempts- максимальное количество попытокinitial_backoff- начальная задержка (секунды)max_backoff- максимальная задержка (секунды)
key_cache- настройки кэширования ключейdriver- драйвер ('memory' или 'redis')ttl- время жизни кэша (секунды)max_size- максимальное количество проектов в кэше
redis- настройки Redis (если используется для кэша)host- хост Redisport- порт Redisdb- номер базы данныхpassword- пароль (опционально)
timeout- настройки таймаутовconnect- таймаут подключения (секунды)request- таймаут запроса (секунды)
Bundle автоматически запрашивает service-token через
issueServiceToken, кеширует его до истеченияexpи переиспользует для удалённых проверок (remote/hybrid/blacklist). Некорректный секрет, неразрешённыйservice_nameили истекший токен приводят к отказу аутентификации. При включённомtcp.tls.enabledрекомендуется указыватьserver_nameи CA файлы; для mTLS добавьтеcert_file/key_file.
Service Authentication
Service Authentication используется для межсервисной аутентификации при вызове методов Auth Service (например, ValidateToken). Это дополнительный слой защиты поверх TLS/mTLS.
Настройка
Service authentication настраивается per-project - каждый проект может иметь свой собственный service_name и service_secret:
octawire_auth: projects: project-1: project_id: 'project-1' service_auth: service_name: 'api-gateway' service_secret: '%env(API_GATEWAY_SERVICE_SECRET)%' project-2: project_id: 'project-2' service_auth: service_name: 'internal-api' service_secret: '%env(INTERNAL_API_SERVICE_SECRET)%'
Как это работает
- Bundle автоматически определяет
project_idиз токена или используетdefault_project - Для каждого
project_idиспользуется соответствующийservice_nameиservice_secretиз конфигурации - При необходимости валидации токена Bundle автоматически выдает service token используя
IssueServiceToken - Service token кэшируется per-project до истечения
exp - Service token используется для аутентификации при вызове методов Auth Service
Обработка ошибок
При неудачной валидации service credentials сервер возвращает ошибку AUTH_FAILED:
- Bundle автоматически обрабатывает
AUTH_FAILEDи выбрасываетAuthenticationExceptionс понятным сообщением - В логах записывается информация о project_id и service_name для отладки
- Ошибка указывает на необходимость проверки конфигурации
service_nameиservice_secretдля конкретного проекта
Безопасное хранение секретов
Важно:
- Не храните
service_secretв коде или конфигурациях - Используйте переменные окружения и secrets manager
- Ротируйте секреты и используйте разные значения для окружений
- Отзывайте скомпрометированные секреты немедленно
Рекомендации:
octawire_auth: projects: project-1: project_id: 'project-1' service_auth: service_name: 'api-gateway' service_secret: '%env(API_GATEWAY_SERVICE_SECRET)%' # Используйте переменные окружения
Кейсы подключения
Bundle поддерживает 4 кейса подключения согласно конфигурациям сервиса:
- PROD + service_auth=false: TLS обязателен (tcp.tls.enabled=true, tcp.tls.required=true), без service auth
- PROD + service_auth=true: TLS обязателен + service authentication
- DEV + service_auth=false: TLS опционален (tcp.tls.enabled=false), без service auth
- DEV + service_auth=true: TLS опционален + service authentication
Пример 1: PROD + service_auth=false
octawire_auth: projects: project-1: transport: 'tcp' tcp: host: 'auth-service.example.com' port: 50052 tls: enabled: true required: true ca_file: '%kernel.project_dir%/config/tls/ca.crt' server_name: 'auth-service.example.com' project_id: 'project-1' # service_auth не указан
Пример 2: PROD + service_auth=true
octawire_auth: projects: project-1: transport: 'tcp' tcp: host: 'auth-service.example.com' port: 50052 tls: enabled: true required: true ca_file: '%kernel.project_dir%/config/tls/ca.crt' cert_file: '%kernel.project_dir%/config/tls/client.crt' # для mTLS key_file: '%kernel.project_dir%/config/tls/client.key' # для mTLS server_name: 'auth-service.example.com' project_id: 'project-1' service_auth: service_name: 'api-gateway' service_secret: '%env(API_GATEWAY_SERVICE_SECRET)%'
Пример 3: DEV + service_auth=false
octawire_auth: projects: project-1: transport: 'tcp' tcp: host: 'localhost' port: 50052 tls: enabled: false # TLS опционален в DEV project_id: 'project-1' # service_auth не указан
Пример 4: DEV + service_auth=true
octawire_auth: projects: project-1: transport: 'tcp' tcp: host: 'localhost' port: 50052 tls: enabled: false # TLS опционален в DEV project_id: 'project-1' service_auth: service_name: 'dev-service' service_secret: 'dev-service-secret-abc123' # для service authentication
Соответствие спецификациям
Bundle полностью соответствует:
- SECURITY.md - требованиям по service authentication и безопасному хранению секретов
- JATP_METHODS_1.0.json - обработке всех кодов ошибок, включая
AUTH_FAILED - Auth Service Protocol v1.0 - camelCase JSON поля
Изменения в v0.9.4 (Protocol v1.0)
camelCase JSON поля
Начиная с v0.9.4, все JSON поля используют camelCase вместо snake_case:
| Старое (snake_case) | Новое (camelCase) |
|---|---|
user_id |
userId |
project_id |
projectId |
token_type |
tokenType |
custom_claims |
customClaims |
access_token |
accessToken |
expires_in |
expiresIn |
Обратная совместимость: Bundle автоматически поддерживает оба формата для входящих данных.
Изменения в DTO
HealthCheckResponse:
// Было (v0.9.3): $response->healthy // bool // Стало (v0.9.4): $response->status // string: "healthy", "degraded", "unhealthy" $response->isHealthy() // bool (helper method)
IssueTokenResponse / RefreshTokenResponse:
// Было (v0.9.3): $response->accessTokenExpiresAt // int (timestamp) // Стало (v0.9.4): $response->expiresIn // int (секунды TTL) $response->refreshExpiresIn // int (секунды TTL)
ValidateTokenRequest:
// v0.9.4: projectId обязателен $request = new ValidateTokenRequest( token: $token, projectId: $projectId, // Обязательно! checkBlacklist: true );
Миграция с v0.9.3
-
Обновите зависимость:
composer require kabiroman/octawire-auth-service-php-client:^0.9.4
-
При использовании
HealthCheckResponse:// Замените: if ($response->healthy) { ... } // На: if ($response->status === 'healthy') { ... } // Или: if ($response->isHealthy()) { ... }
-
При использовании
expiresAt:// Замените: $expiresAt = $response->accessTokenExpiresAt; // На: $expiresAt = time() + $response->expiresIn;
Обработка ошибок
Bundle автоматически обрабатывает ошибки валидации токенов:
InvalidTokenException→BadCredentialsExceptionTokenExpiredException→BadCredentialsExceptionTokenRevokedException→BadCredentialsException
Все ошибки возвращаются в формате JSON с кодом 401 (Unauthorized).
Примеры
Полные примеры использования находятся в директории examples/:
examples/symfony-app/- пример Symfony приложенияexamples/integration-tests/- примеры интеграционных тестов с Auth Service
Быстрый старт тестирования
# 1. Запустить Auth Service ./auth-service --config config/config.test.local.json # 2. Тест клиента php examples/integration-tests/test-client-integration.php # 3. HTTP тест (требует Symfony сервер) php examples/integration-tests/test-http-integration.php
Подробнее: TESTING.md
Лицензия
MIT License