Skip to content

Commit

Permalink
Merge pull request #159 from sai-gillingham/feature/logout_remove_tokens
Browse files Browse the repository at this point in the history
ログアウト機能の作成。
  • Loading branch information
kiy0taka authored Sep 22, 2023
2 parents caa5949 + 38e8602 commit 53c179c
Show file tree
Hide file tree
Showing 4 changed files with 281 additions and 19 deletions.
59 changes: 59 additions & 0 deletions Controller/ApiController.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,16 @@
use Eccube\Controller\AbstractController;
use Eccube\Http\JsonResponse;
use Eccube\Http\Response;
use Eccube\Security\SecurityContext;
use GraphQL\Error\DebugFlag;
use GraphQL\Error\Error;
use GraphQL\GraphQL;
use League\Bundle\OAuth2ServerBundle\Manager\AccessTokenManagerInterface;
use League\Bundle\OAuth2ServerBundle\Manager\RefreshTokenManagerInterface;
use League\Bundle\OAuth2ServerBundle\Model\AccessToken;
use League\Bundle\OAuth2ServerBundle\Model\RefreshToken;
use League\Bundle\OAuth2ServerBundle\Repository\AccessTokenRepository;
use League\Bundle\OAuth2ServerBundle\Repository\RefreshTokenRepository;
use Plugin\Api42\GraphQL\Schema;
use Plugin\Api42\GraphQL\Types;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\IsGranted;
Expand All @@ -42,15 +49,31 @@ class ApiController extends AbstractController
* @var Schema
*/
private $schema;
private SecurityContext $securityContext;
private RefreshTokenRepository $refreshTokenRepository;
private AccessTokenRepository $accessTokenRepository;
private RefreshTokenManagerInterface $refreshTokenManager;
private AccessTokenManagerInterface $accessTokenManager;

public function __construct(
Types $types,
KernelInterface $kernel,
Schema $schema,
SecurityContext $securityContext,
RefreshTokenRepository $refreshTokenRepository,
AccessTokenRepository $accessTokenRepository,
RefreshTokenManagerInterface $refreshTokenManager,
AccessTokenManagerInterface $accessTokenManager
) {
$this->types = $types;
$this->kernel = $kernel;
$this->schema = $schema;
$this->securityContext = $securityContext;
$this->refreshTokenRepository = $refreshTokenRepository;

$this->accessTokenRepository = $accessTokenRepository;
$this->refreshTokenManager = $refreshTokenManager;
$this->accessTokenManager = $accessTokenManager;
}

/**
Expand Down Expand Up @@ -108,4 +131,40 @@ public function index(Request $request)

return $jsonResult;
}

/**
* ログアウトしてOAuth2のセッションを無効化する.
* @Route("/api/logout", name="api_logout", methods={"POST", "OPTIONS"})
*/
public function logoutAndInvalidateOAuth2Session(): JsonResponse
{
$user = $this->securityContext->getLoginUser();
if ($user !== null) {
/** @var AccessToken[]|null $tokenList */
$tokenList = $this->entityManager->getRepository(AccessToken::class)->findBy(['userIdentifier' => $user->getUsername()]);
foreach ($tokenList as $tokenRow) {
$refreshTokenList = $this->entityManager->getRepository(RefreshToken::class)->findBy(['accessToken' => $tokenRow->getIdentifier()]);
foreach ($refreshTokenList as $refreshTokenRow) {
// ユーザーのリフレッシュトークンを削除
$this->refreshTokenRepository->revokeRefreshToken($refreshTokenRow->getIdentifier());
$this->entityManager->flush();
}

// ユーザーのアクセストークンを削除
$this->accessTokenRepository->revokeAccessToken($tokenRow->getIdentifier());
$this->entityManager->flush();
}
} else {
log_alert('IGNORED, NO ACTIVE USER');
}

// 他の有効期限切れたトークンを削除
$this->accessTokenManager->clearExpired();
$this->refreshTokenManager->clearExpired();

$jsonResponse = new JsonResponse();
$jsonResponse->setContent(json_encode(['message' => 'success']));

return $jsonResponse;
}
}
8 changes: 8 additions & 0 deletions DependencyInjection/ApiExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,14 @@ public function prepend(ContainerBuilder $container)
foreach ($names as $name) {
// adminの前にapiを追加する
if ($name === 'admin') {
// ログアウトの設定を追加
$replaced['api_logout'] = [
'pattern' => '^/api/logout',
'security' => true,
'stateless' => true,
'oauth2' => true,
'provider' => 'user_provider'
];
$replaced['api'] = [
'pattern' => '^/api',
'security' => true,
Expand Down
13 changes: 11 additions & 2 deletions Event.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
namespace Plugin\Api42;

use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\Event\ExceptionEvent;
use Symfony\Component\HttpKernel\Event\ResponseEvent;
use Symfony\Component\HttpKernel\KernelEvents;

Expand All @@ -29,19 +30,27 @@ public static function getSubscribedEvents()
{
return [
KernelEvents::RESPONSE => 'onKernelResponse',
KernelEvents::EXCEPTION => 'onKernelResponse',
];
}

/**
* OPTIONメソッドの場合は、処理を中断する.
*
* @param ExceptionEvent|ResponseEvent $event
*
* @return void
*/
public function onKernelResponse(ResponseEvent $event)
public function onKernelResponse(ExceptionEvent|ResponseEvent $event): void
{
$request = $event->getRequest();
if ($request->getMethod() === 'OPTIONS' || $request->getMethod() === 'POST' && ($request->attributes->get('_route') === 'oauth2_token' || $request->attributes->get('_route') === 'oauth2_authorize') || $request->attributes->get('_route') === 'api') {
if ($request->getMethod() === 'OPTIONS' || $request->getMethod() === 'POST' && ($request->attributes->get('_route') === 'oauth2_token' || $request->attributes->get('_route') === 'api_logout' || $request->attributes->get('_route') === 'oauth2_authorize') || $request->attributes->get('_route') === 'api') {

$response = $event->getResponse();
if ($response === null) {
return;
}

$response->headers->add([
'Access-Control-Allow-Origin' => '*',
'Content-Type' => 'application/json',
Expand Down
Loading

0 comments on commit 53c179c

Please sign in to comment.