Skip to content

Commit

Permalink
Forward exception code to the response status code
Browse files Browse the repository at this point in the history
  • Loading branch information
theofidry authored and chalasr committed Jul 14, 2021
1 parent ed81a4f commit 1e1e5ca
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 1 deletion.
19 changes: 18 additions & 1 deletion Security/Http/Authentication/AuthenticationFailureHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
use Lexik\Bundle\JWTAuthenticationBundle\Events;
use Lexik\Bundle\JWTAuthenticationBundle\Response\JWTAuthenticationFailureResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Http\Authentication\AuthenticationFailureHandlerInterface;
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
Expand Down Expand Up @@ -33,13 +34,29 @@ public function __construct(EventDispatcherInterface $dispatcher)
public function onAuthenticationFailure(Request $request, AuthenticationException $exception)
{
$errorMessage = strtr($exception->getMessageKey(), $exception->getMessageData());
$statusCode = self::mapExceptionCodeToStatusCode($exception->getCode());

$event = new AuthenticationFailureEvent(
$exception,
new JWTAuthenticationFailureResponse($errorMessage)
new JWTAuthenticationFailureResponse($errorMessage, $statusCode)
);

$this->dispatcher->dispatch($event, Events::AUTHENTICATION_FAILURE);

return $event->getResponse();
}

/**
* @param string|int $exceptionCode
*/
private static function mapExceptionCodeToStatusCode($exceptionCode): int
{
$canMapToStatusCode = is_int($exceptionCode)
&& $exceptionCode >= 400
&& $exceptionCode < 500;

return $canMapToStatusCode
? $exceptionCode
: Response::HTTP_UNAUTHORIZED;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace Lexik\Bundle\JWTAuthenticationBundle\Tests\Security\Http\Authentication;

use Exception;
use Lexik\Bundle\JWTAuthenticationBundle\Security\Http\Authentication\AuthenticationFailureHandler;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
Expand Down Expand Up @@ -35,6 +36,63 @@ public function testOnAuthenticationFailure()
$this->assertEquals($authenticationException->getMessageKey(), $content['message']);
}

/**
* test onAuthenticationFailure method.
*/
public function testOnAuthenticationFailureWithANonDefaultHttpFailureStatusCode()
{
$dispatcher = $this
->getMockBuilder('Symfony\Component\EventDispatcher\EventDispatcherInterface')
->disableOriginalConstructor()
->getMock();

$authenticationException = new AuthenticationException('', 403);

$handler = new AuthenticationFailureHandler($dispatcher);
$response = $handler->onAuthenticationFailure($this->getRequest(), $authenticationException);
$content = json_decode($response->getContent(), true);

$this->assertInstanceOf('Symfony\Component\HttpFoundation\JsonResponse', $response);
$this->assertEquals(403, $response->getStatusCode());
$this->assertEquals(403, $content['code']);
$this->assertEquals($authenticationException->getMessageKey(), $content['message']);
}

/**
* test onAuthenticationFailure method.
*
* @dataProvider nonHttpStatusCodeProvider
*
* @param string|int $nonHttpStatusCode
*/
public function testOnAuthenticationFailureWithANonHttpStatusCode($nonHttpStatusCode)
{
$dispatcher = $this
->getMockBuilder('Symfony\Component\EventDispatcher\EventDispatcherInterface')
->disableOriginalConstructor()
->getMock();

$authenticationException = new AuthenticationException('', $nonHttpStatusCode);

$handler = new AuthenticationFailureHandler($dispatcher);
$response = $handler->onAuthenticationFailure($this->getRequest(), $authenticationException);
$content = json_decode($response->getContent(), true);

$this->assertInstanceOf('Symfony\Component\HttpFoundation\JsonResponse', $response);
$this->assertEquals(401, $response->getStatusCode());
$this->assertEquals(401, $content['code']);
$this->assertEquals($authenticationException->getMessageKey(), $content['message']);
}

public static function nonHttpStatusCodeProvider(): iterable
{
yield 'server error HTTP status code' => [500];
yield 'redirection HTTP status code' => [500];
yield 'success HTTP status code' => [500];
yield 'non HTTP status code' => [1302];
yield 'default status code' => [0];
}

/**
* @return \PHPUnit_Framework_MockObject_MockObject
*/
Expand Down

0 comments on commit 1e1e5ca

Please sign in to comment.