Skip to content

Commit

Permalink
improved UnauthorizedException throwing, introduced dedicated exception
Browse files Browse the repository at this point in the history
  • Loading branch information
konradoboza committed Jun 7, 2024
1 parent 5c75500 commit 9c8f8c2
Show file tree
Hide file tree
Showing 7 changed files with 43 additions and 26 deletions.
9 changes: 3 additions & 6 deletions src/bundle/EventListener/CsrfListener.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
namespace Ibexa\Bundle\Rest\EventListener;

use Ibexa\Bundle\Rest\RestEvents;
use Ibexa\Core\Base\Exceptions\UnauthorizedException;
use Ibexa\Contracts\Rest\Exceptions\UnauthorizedException;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\Request;
Expand Down Expand Up @@ -59,7 +59,7 @@ public static function getSubscribedEvents(): array
/**
* This method validates CSRF token if CSRF protection is enabled.
*
* @throws \Ibexa\Core\Base\Exceptions\UnauthorizedException
* @throws \Ibexa\Contracts\Core\Repository\Exceptions\UnauthorizedException
*/
public function onKernelRequest(RequestEvent $event): void
{
Expand All @@ -86,10 +86,7 @@ public function onKernelRequest(RequestEvent $event): void
}

if (!$this->checkCsrfToken($request)) {
throw new UnauthorizedException(
'Missing or invalid CSRF token',
$request->getMethod() . ' ' . $request->getPathInfo()
);
throw new UnauthorizedException('Missing or invalid CSRF token');
}

// Dispatching event so that CSRF token intention can be injected into Legacy Stack
Expand Down
23 changes: 23 additions & 0 deletions src/contracts/Exceptions/UnauthorizedException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?php

/**
* @copyright Copyright (C) Ibexa AS. All rights reserved.
* @license For full copyright and license information view LICENSE file distributed with this source code.
*/
declare(strict_types=1);

namespace Ibexa\Contracts\Rest\Exceptions;

use Ibexa\Contracts\Core\Repository\Exceptions\UnauthorizedException as ApiUnauthorizedException;
use Throwable;

final class UnauthorizedException extends ApiUnauthorizedException
{
public function __construct(
string $message = '',
int $code = 401,
?Throwable $previous = null
) {
parent::__construct($message, $code, $previous);
}
}
6 changes: 5 additions & 1 deletion src/lib/Security/Authenticator/RestAuthenticator.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

namespace Ibexa\Rest\Security\Authenticator;

use Ibexa\Contracts\Rest\Exceptions\UnauthorizedException;
use Ibexa\Rest\Input\Dispatcher;
use Ibexa\Rest\Message;
use Symfony\Component\HttpFoundation\Request;
Expand Down Expand Up @@ -76,9 +77,12 @@ public function onAuthenticationSuccess(
return null;
}

/**
* @throws \Ibexa\Contracts\Core\Repository\Exceptions\UnauthorizedException
*/
public function onAuthenticationFailure(Request $request, AuthenticationException $exception): ?Response
{
throw $exception;
throw new UnauthorizedException($exception->getMessage());
}

public function isInteractive(): bool
Expand Down
4 changes: 2 additions & 2 deletions src/lib/Server/Controller/JWT.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

namespace Ibexa\Rest\Server\Controller;

use Ibexa\Core\Base\Exceptions\UnauthorizedException;
use Ibexa\Contracts\Rest\Exceptions\UnauthorizedException;
use Ibexa\Core\MVC\Symfony\Security\Authentication\AuthenticatorInterface;
use Ibexa\Rest\Message;
use Ibexa\Rest\Server\Controller as RestController;
Expand Down Expand Up @@ -57,7 +57,7 @@ public function createToken(Request $request): Values\JWT
return new Values\JWT($jwtToken);
} catch (AuthenticationException $e) {
$this->getAuthenticator()->logout($request);
throw new UnauthorizedException('Invalid login or password', $request->getPathInfo());
throw new UnauthorizedException('Invalid login or password');
}
}

Expand Down
15 changes: 6 additions & 9 deletions src/lib/Server/Controller/SessionController.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
use Ibexa\Contracts\Core\Repository\PermissionResolver;
use Ibexa\Contracts\Core\Repository\UserService;
use Ibexa\Contracts\Core\SiteAccess\ConfigResolverInterface;
use Ibexa\Core\Base\Exceptions\UnauthorizedException;
use Ibexa\Contracts\Rest\Exceptions\UnauthorizedException;
use Ibexa\Rest\Server\Controller;
use Ibexa\Rest\Server\Exceptions;
use Ibexa\Rest\Server\Security\CsrfTokenManager;
Expand Down Expand Up @@ -47,7 +47,7 @@ public function createSessionAction(Request $request): RestValue
$token = $this->securityTokenStorage->getToken();

if ($token === null) {
throw new UnauthorizedException('authorization', 'The current user is not authenticated.');
throw new UnauthorizedException('The current user is not authenticated.');
}

/** @var \Ibexa\Core\MVC\Symfony\Security\User $user */
Expand All @@ -64,9 +64,9 @@ public function createSessionAction(Request $request): RestValue
// Already logged in with another user, this will be converted to HTTP status 409
return new Values\Conflict();
} catch (AuthenticationException $e) {
throw new UnauthorizedException('Invalid login or password', $request->getPathInfo());
throw new UnauthorizedException('Invalid login or password');
} catch (AccessDeniedException $e) {
throw new UnauthorizedException($e->getMessage(), $request->getPathInfo());
throw new UnauthorizedException($e->getMessage());
}
}

Expand Down Expand Up @@ -159,7 +159,7 @@ private function hasStoredCsrfToken(): bool
/**
* Checks the presence / validity of the CSRF token.
*
* @throws \Ibexa\Core\Base\Exceptions\UnauthorizedException if the token is missing or invalid
* @throws \Ibexa\Contracts\Core\Repository\Exceptions\UnauthorizedException if the token is missing or invalid
*/
private function checkCsrfToken(Request $request): void
{
Expand All @@ -184,10 +184,7 @@ private function getCsrfToken(): string

private function createInvalidCsrfTokenException(Request $request): UnauthorizedException
{
return new UnauthorizedException(
'Missing or invalid CSRF token',
$request->getMethod() . ' ' . $request->getPathInfo()
);
return new UnauthorizedException('Missing or invalid CSRF token');
}

private function logout(Request $request): Response
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,16 @@
* @copyright Copyright (C) Ibexa AS. All rights reserved.
* @license For full copyright and license information view LICENSE file distributed with this source code.
*/
declare(strict_types=1);

namespace Ibexa\Rest\Server\Output\ValueObjectVisitor;

/**
* UnauthorizedException value object visitor.
*/
class UnauthorizedException extends Exception
final class UnauthorizedException extends Exception
{
/**
* Returns HTTP status code.
*
* @return int
*/
protected function getStatus()
protected function getStatus(): int
{
return 401;
}
Expand Down
2 changes: 1 addition & 1 deletion tests/bundle/EventListener/CsrfListenerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
namespace Ibexa\Tests\Bundle\Rest\EventListener;

use Ibexa\Bundle\Rest\EventListener\CsrfListener;
use Ibexa\Core\Base\Exceptions\UnauthorizedException;
use Ibexa\Contracts\Rest\Exceptions\UnauthorizedException;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\HttpFoundation\HeaderBag;
use Symfony\Component\HttpFoundation\ParameterBag;
Expand Down

0 comments on commit 9c8f8c2

Please sign in to comment.