diff --git a/Resources/doc/2-data-customization.md b/Resources/doc/2-data-customization.md index b777c97c..b9beecfb 100644 --- a/Resources/doc/2-data-customization.md +++ b/Resources/doc/2-data-customization.md @@ -169,8 +169,6 @@ public function onAuthenticationSuccessResponse(AuthenticationSuccessEvent $even return; } - // $data['token'] contains the JWT - $data['data'] = array( 'roles' => $user->getRoles(), ); @@ -199,7 +197,7 @@ public function onJwtEncoded(JWTEncodedEvent $event) #### Events::AUTHENTICATION_FAILURE - customize the failure response -By default, the response in case of failed authentication is just a json containing a "Bad credentials" message and a 401 status code, but you can set a custom response. +By default, the response in case of failed authentication is just a json containing a failure message and a 401 status code, but you can set a custom response. ``` yaml # services.yml @@ -214,6 +212,9 @@ Example 7: set a custom response on authentication failure ``` php // Acme\Bundle\ApiBundle\EventListener\AuthenticationFailureListener.php + +use Lexik\Bundle\JWTAuthenticationBundle\Response\JWTAuthenticationFailureResponse; + /** * @param AuthenticationFailureEvent $event */ @@ -224,7 +225,7 @@ public function onAuthenticationFailureResponse(AuthenticationFailureEvent $even 'message' => 'Bad credentials, please verify that your username/password are correctly set', ]; - $response = new JsonResponse($data, 401); + $response = new JWTAuthenticationFailureResponse($data); $event->setResponse($response); } @@ -243,21 +244,19 @@ services: - { name: kernel.event_listener, event: lexik_jwt_authentication.on_jwt_invalid, method: onJWTInvalid } ``` -Example 8: set a custom response message on invalid token +Example 8: set a custom response message and status code on invalid token ``` php // Acme\Bundle\ApiBundle\EventListener\JWTInvalidListener.php + +use Lexik\Bundle\JWTAuthenticationBundle\Response\JWTAuthenticationFailureResponse; + /** * @param JWTInvalidEvent $event */ public function onJWTInvalid(JWTInvalidEvent $event) { - $data = [ - 'status' => '403 Forbidden', - 'message' => 'Your token is invalid, please login again to get a new one', - ]; - - $response = new JsonResponse($data, 403); + $response = new JWTAuthenticationFailureResponse('Your token is invalid, please login again to get a new one', 403); $event->setResponse($response); } diff --git a/Response/JWTAuthenticationFailureResponse.php b/Response/JWTAuthenticationFailureResponse.php index 58296c33..a09f57a7 100644 --- a/Response/JWTAuthenticationFailureResponse.php +++ b/Response/JWTAuthenticationFailureResponse.php @@ -25,16 +25,11 @@ final class JWTAuthenticationFailureResponse extends JsonResponse /** * @param string $message A failure message passed in the response body */ - public function __construct($message = 'Bad credentials') + public function __construct($message = 'Bad credentials', $statusCode = JsonResponse::HTTP_UNAUTHORIZED) { $this->message = $message; - parent::__construct(null, self::HTTP_UNAUTHORIZED, ['WWW-Authenticate' => 'Bearer']); - - $this->setData([ - 'code' => $this->statusCode, - 'message' => $this->message, - ]); + parent::__construct(null, $statusCode, ['WWW-Authenticate' => 'Bearer']); } /** @@ -60,4 +55,14 @@ public function getMessage() { return $this->message; } + + /** + * Sets the response data with the statusCode & message included. + * + * {@inheritdoc} + */ + public function setData($data = []) + { + parent::setData(['code' => $this->statusCode, 'message' => $this->message] + (array) $data); + } } diff --git a/Response/JWTAuthenticationSuccessResponse.php b/Response/JWTAuthenticationSuccessResponse.php index eb91a58f..8ff8cbe7 100644 --- a/Response/JWTAuthenticationSuccessResponse.php +++ b/Response/JWTAuthenticationSuccessResponse.php @@ -23,67 +23,23 @@ final class JWTAuthenticationSuccessResponse extends JsonResponse private $token; /** - * @param string $token Json Web Token - * @param array $data Extra data passed to the response body. - * @param array $headers HTTP headers + * @param string $token Json Web Token + * @param array $data Extra data passed to the response. */ - public function __construct($token, array $extraData = []) + public function __construct($token, array $data = null) { - $this->token = $token; - $this->extraData = $extraData; + $this->token = $token; - parent::__construct(); - - $this->setBody(); + parent::__construct($data); } /** - * Gets the Json Web Token. - * - * @return string - */ - public function getToken() - { - return $this->token; - } - - /** - * {@inheritdoc} - */ - public function setExtraData(array $extraData = []) - { - $this->extraData = $extraData; - - return $this; - } - - /** - * {@inheritdoc} - */ - public function getExtraData() - { - return $this->extraData; - } - - /** - * Prevents unexpected response content. - * - * @internal + * Sets the response data with the JWT included. * * {@inheritdoc} */ public function setData($data = []) { - return $this->setBody(); - } - - /** - * Creates the response body. - * - * @return JWTAuthenticationSuccessResponse - */ - private function setBody() - { - parent::setData(['token' => $this->token] + $this->extraData); + parent::setData(['token' => $this->token] + (array) $data); } } diff --git a/Security/Http/Authentication/AuthenticationSuccessHandler.php b/Security/Http/Authentication/AuthenticationSuccessHandler.php index d052ca68..6b904f2d 100644 --- a/Security/Http/Authentication/AuthenticationSuccessHandler.php +++ b/Security/Http/Authentication/AuthenticationSuccessHandler.php @@ -49,7 +49,7 @@ public function onAuthenticationSuccess(Request $request, TokenInterface $token) $event = new AuthenticationSuccessEvent(['token' => $jwt], $user, $request, $response); $this->dispatcher->dispatch(Events::AUTHENTICATION_SUCCESS, $event); - $response->setExtraData($event->getData()); + $response->setData($event->getData()); return $response; } diff --git a/Tests/Functional/config/config.yml b/Tests/Functional/config/config.yml index 20718045..bbc4eecf 100644 --- a/Tests/Functional/config/config.yml +++ b/Tests/Functional/config/config.yml @@ -4,8 +4,8 @@ framework: resource: %kernel.root_dir%/config/routing.yml lexik_jwt_authentication: - private_key_path: %kernel.root_dir%/var/private.pem - public_key_path: %kernel.root_dir%/var/public.pem + private_key_path: '%kernel.root_dir%/var/private.pem' + public_key_path: '%kernel.root_dir%/var/public.pem' pass_phrase: testing security: diff --git a/Tests/Response/JWTAuthenticationSuccessResponseTest.php b/Tests/Response/JWTAuthenticationSuccessResponseTest.php index e7b74d0e..045e3f82 100644 --- a/Tests/Response/JWTAuthenticationSuccessResponseTest.php +++ b/Tests/Response/JWTAuthenticationSuccessResponseTest.php @@ -13,18 +13,14 @@ final class JWTAuthenticationSuccessResponseTest extends \PHPUnit_Framework_Test { public function testResponse() { - $extraData = [ + $data = [ 'username' => 'foobar', 'email' => 'dev@lexik.fr' ]; - $expected = ['token' => 'jwt'] + $extraData; + $expected = ['token' => 'jwt'] + $data; + $response = new JWTAuthenticationSuccessResponse($expected['token'], $data); - $response = new JWTAuthenticationSuccessResponse($expected['token'], $extraData); - - $this->assertSame($expected['token'], $response->getToken()); $this->assertSame(200, $response->getStatusCode()); - $this->assertSame($extraData, $response->getExtraData()); - $this->assertSame(json_encode($expected), $response->getContent()); return $response; @@ -40,9 +36,7 @@ public function testReplaceData(JWTAuthenticationSuccessResponse $response) // Test that the previous method call has no effect on the original body $this->assertNotEquals(json_encode($replacementData), $response->getContent()); - $this->assertSame( - json_encode(['token' => $response->getToken()] + $response->getExtraData()), - $response->getContent() - ); + $this->assertAttributeSame($replacementData['foo'], 'foo', json_decode($response->getContent())); + $this->assertAttributeNotEmpty('token', json_decode($response->getContent())); } }