Skip to content

Commit

Permalink
Merge pull request #62 from Nyholm/patch-exception
Browse files Browse the repository at this point in the history
Throw exceptions instead of creating responses
  • Loading branch information
HypeMC committed Jun 6, 2019
2 parents 1fd6e76 + 1a9cb81 commit 8a505f6
Show file tree
Hide file tree
Showing 8 changed files with 89 additions and 7 deletions.
8 changes: 8 additions & 0 deletions DependencyInjection/Configuration.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,14 @@ public function getConfigTreeBuilder()
$rootNode->append($this->createScopesNode());
$rootNode->append($this->createPersistenceNode());

$rootNode
->children()
->scalarNode('exception_event_listener_priority')
->info('The priority of the event listener that converts an Exception to a Response')
->defaultValue(10)
->end()
->end();

return $treeBuilder;
}

Expand Down
8 changes: 8 additions & 0 deletions DependencyInjection/TrikoderOAuth2Extension.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
use Symfony\Component\DependencyInjection\Extension\PrependExtensionInterface;
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\HttpKernel\KernelEvents;
use Trikoder\Bundle\OAuth2Bundle\DBAL\Type\Grant as GrantType;
use Trikoder\Bundle\OAuth2Bundle\DBAL\Type\RedirectUri as RedirectUriType;
use Trikoder\Bundle\OAuth2Bundle\DBAL\Type\Scope as ScopeType;
Expand All @@ -46,6 +47,13 @@ public function load(array $configs, ContainerBuilder $container)
$this->configureAuthorizationServer($container, $config['authorization_server']);
$this->configureResourceServer($container, $config['resource_server']);
$this->configureScopes($container, $config['scopes']);

$container->getDefinition('trikoder.oauth2.event_listener.authorization.convert_to_response')
->addTag('kernel.event_listener', [
'event' => KernelEvents::EXCEPTION,
'method' => 'onKernelException',
'priority' => $config['exception_event_listener_priority'],
]);
}

/**
Expand Down
24 changes: 24 additions & 0 deletions EventListener/ConvertExceptionToResponseListener.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php

declare(strict_types=1);

namespace Trikoder\Bundle\OAuth2Bundle\EventListener;

use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
use Trikoder\Bundle\OAuth2Bundle\Security\Exception\InsufficientScopesException;
use Trikoder\Bundle\OAuth2Bundle\Security\Exception\Oauth2AuthenticationFailedException;

/**
* @author Tobias Nyholm <[email protected]>
*/
final class ConvertExceptionToResponseListener
{
public function onKernelException(GetResponseForExceptionEvent $event)
{
$exception = $event->getException();
if ($exception instanceof InsufficientScopesException || $exception instanceof Oauth2AuthenticationFailedException) {
$event->setResponse(new Response($exception->getMessage(), $exception->getCode()));
}
}
}
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,10 @@ This package is currently in the active development.
entity_manager: default # Required
in_memory: ~
# The priority of the event listener that converts an Exception to a Response
exception_event_listener_priority: 10
```

3. Enable the bundle in `config/bundles.php` by adding it to the array:
Expand Down
1 change: 1 addition & 0 deletions Resources/config/services.xml
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@
<argument type="service" id="Symfony\Component\Security\Core\Security" />
<tag name="kernel.event_listener" event="trikoder.oauth2.authorization_request_resolve" method="onAuthorizationRequest" priority="1024" />
</service>
<service id="trikoder.oauth2.event_listener.authorization.convert_to_response" class="Trikoder\Bundle\OAuth2Bundle\EventListener\ConvertExceptionToResponseListener" />

<!-- Token controller -->
<service id="trikoder.oauth2.controller.token_controller" class="Trikoder\Bundle\OAuth2Bundle\Controller\TokenController">
Expand Down
22 changes: 22 additions & 0 deletions Security/Exception/InsufficientScopesException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?php

declare(strict_types=1);

namespace Trikoder\Bundle\OAuth2Bundle\Security\Exception;

use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationException;

/**
* @author Tobias Nyholm <[email protected]>
*/
class InsufficientScopesException extends AuthenticationException
{
public static function create(TokenInterface $token): self
{
$exception = new self('The token has insufficient scopes.', 403);
$exception->setToken($token);

return $exception;
}
}
18 changes: 18 additions & 0 deletions Security/Exception/Oauth2AuthenticationFailedException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php

declare(strict_types=1);

namespace Trikoder\Bundle\OAuth2Bundle\Security\Exception;

use Symfony\Component\Security\Core\Exception\AuthenticationException;

/**
* @author Tobias Nyholm <[email protected]>
*/
class Oauth2AuthenticationFailedException extends AuthenticationException
{
public static function create(string $message): self
{
return new self($message, 401);
}
}
11 changes: 4 additions & 7 deletions Security/Firewall/OAuth2Listener.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,14 @@

use Symfony\Bridge\PsrHttpMessage\HttpMessageFactoryInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Http\Firewall\ListenerInterface;
use Trikoder\Bundle\OAuth2Bundle\Security\Authentication\Token\OAuth2Token;
use Trikoder\Bundle\OAuth2Bundle\Security\Exception\InsufficientScopesException;
use Trikoder\Bundle\OAuth2Bundle\Security\Exception\Oauth2AuthenticationFailedException;

final class OAuth2Listener implements ListenerInterface
{
Expand Down Expand Up @@ -56,15 +57,11 @@ public function handle(GetResponseEvent $event)
/** @var OAuth2Token $authenticatedToken */
$authenticatedToken = $this->authenticationManager->authenticate(new OAuth2Token($request, null));
} catch (AuthenticationException $e) {
$event->setResponse(new Response($e->getMessage(), Response::HTTP_UNAUTHORIZED));

return;
throw Oauth2AuthenticationFailedException::create($e->getMessage());
}

if (!$this->isAccessToRouteGranted($event->getRequest(), $authenticatedToken)) {
$event->setResponse(new Response('The token has insufficient scopes.', Response::HTTP_FORBIDDEN));

return;
throw InsufficientScopesException::create($authenticatedToken);
}

$this->tokenStorage->setToken($authenticatedToken);
Expand Down

0 comments on commit 8a505f6

Please sign in to comment.