Как совместить JWT и OAuth в Symfony?

В Symfony есть несколько способов совместить JWT (JSON Web Tokens) и OAuth для аутентификации и авторизации пользователей.

1. Установка зависимостей:
- Сначала вам нужно установить необходимые библиотеки для работы с JWT и OAuth. Для JWT вы можете использовать firebase/php-jwt, а для OAuth - league/oauth2-server.
- Выполните команду composer require firebase/php-jwt league/oauth2-server для установки этих библиотек.

2. Настройка аутентификации и авторизации:
- Создайте класс TokenController, который будет отвечать за выдачу токенов:

namespace AppController;

use SymfonyComponentHttpFoundationRequest;
use SymfonyComponentRoutingAnnotationRoute;
use FirebaseJWTJWT;
use LeagueOAuth2ServerGrantPasswordGrant;

class TokenController
{
    /**
     * @Route("/token", name="token", methods={"POST"})
     */
    public function token(Request $request)
    {
        // Проверка учетных данных пользователя
        $clientId = $request->request->get('client_id');
        $clientSecret = $request->request->get('client_secret');
        // Реализуйте свою логику проверки учетных данных пользователя

        // Генерация JWT токена
        $token = array(
            'client_id' => $clientId,
            'scope' => 'api',
            // Другие данные, которые вы хотите добавить в токен
            // Например, информация о пользователе
        );

        $jwt = JWT::encode($token, 'your_secret_key');

        return new JsonResponse(array(
            'access_token' => $jwt,
            'token_type' => 'Bearer',
            'expires_in' => 3600, // Количество секунд до истечения срока действия токена
        ));
    }
}

3. Настройка маршрута:
- Добавьте маршрут в файл config/routes.yaml:

token_route:
    path: /token
    controller: AppControllerTokenController::token

4. Настройка проверки токена:
- Создайте класс SecurityController, который будет отвечать за проверку токена перед доступом к защищенным ресурсам:

namespace AppController;

use SymfonyComponentHttpFoundationRequest;
use SymfonyComponentRoutingAnnotationRoute;
use FirebaseJWTJWT;

class SecurityController
{
    /**
     * @Route("/{id}", name="resource", methods={"GET"})
     */
    public function resource(Request $request, $id)
    {
        // Проверка JWT токена
        $token = $request->headers->get('Authorization');
        // Извлекайте и проверяйте JWT токен с помощью библиотеки firebase/php-jwt

        // Доступ к ресурсу
        return new JsonResponse(array(
            'data' => 'Resource ' . $id,
        ));
    }
}

5. Настройка маршрута для доступа к защищенным ресурсам:
- Добавьте маршрут в файл config/routes.yaml:

resource_route:
    path: /resource/{id}
    controller: AppControllerSecurityController::resource

6. Конфигурация OAuth сервера:
- Создайте класс OAuthServerFactory, который будет настраивать OAuth сервер:

namespace AppFactory;

use SymfonyComponentHttpFoundationRequest;
use SymfonyComponentRoutingAnnotationRoute;
use FirebaseJWTJWT;
use LeagueOAuth2ServerRequestTypesAuthorizationRequest;
use LeagueOAuth2ServerAuthorizationServer;
use LeagueOAuth2ServerResourceServer;
use LeagueOAuth2ServerGrantPasswordGrant;
use PsrHttpMessageServerRequestInterface;

class OAuthServerFactory
{
    public static function create()
    {
        // Создание экземпляра OAuth сервера
        $server = new AuthorizationServer();

        // Настройка хранилища для клиентов
        $clientRepository = new ClientRepository();
        $server->setClientRepository($clientRepository);

        // Настройка хранилища для access и refresh токенов
        $accessTokenRepository = new AccessTokenRepository();
        $refreshTokenRepository = new RefreshTokenRepository();
        $server->setAccessTokenRepository($accessTokenRepository);
        $server->setRefreshTokenRepository($refreshTokenRepository);

        // Настройка доступных грантов
        $passwordGrant = new PasswordGrant($userRepository);
        $server->enableGrantType($passwordGrant);

        return $server;
    }
}

7. Привязка OAuth сервера к приложению:
- Отредактируйте файл config/services.yaml:

services:
    ...
    AppFactoryOAuthServerFactory:
        autowire: true

    LeagueOAuth2ServerResourceServer:
        factory: ['@AppFactoryOAuthServerFactory', 'create']
        public: true

8. Использование OAuth сервера для проверки токена:
- Отредактируйте класс SecurityController для проверки OAuth токена:

namespace AppController;

use SymfonyComponentHttpFoundationRequest;
use SymfonyComponentRoutingAnnotationRoute;
use FirebaseJWTJWT;
use LeagueOAuth2ServerResourceServer;

class SecurityController
{
    private $resourceServer;

    public function __construct(ResourceServer $resourceServer)
    {
        $this->resourceServer = $resourceServer;
    }

    /**
     * @Route("/{id}", name="resource", methods={"GET"})
     */
    public function resource(Request $request, $id)
    {
        // Проверка OAuth токена
        $psrRequest = $request->duplicate()->createRequest($request);
        $response = $this->resourceServer->validateAuthenticatedRequest($psrRequest);
        if ($response->getStatusCode() !== 200) {
            throw new AccessDeniedHttpException('Invalid access token');
        }

        // Доступ к ресурсу
        return new JsonResponse(array(
            'data' => 'Resource ' . $id,
        ));
    }
}

Теперь у вас есть совмещенная настройка JWT и OAuth для аутентификации и авторизации в Symfony. Обратите внимание, что данный пример является общим и может потребовать дополнительной настройки в зависимости от ваших потребностей.