Skip to content

Commit

Permalink
Add ApiSecurityTest
Browse files Browse the repository at this point in the history
  • Loading branch information
Morgan Pichat committed Feb 16, 2024
1 parent e3ca88b commit 5a97714
Show file tree
Hide file tree
Showing 4 changed files with 200 additions and 8 deletions.
6 changes: 6 additions & 0 deletions app/config/config_test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -55,3 +55,9 @@ monolog:
VERBOSITY_VERY_VERBOSE: NOTICE
VERBOSITY_DEBUG: DEBUG
channels: [ "doctrine" ]

api_platform:
mapping:
paths:
- '%kernel.project_dir%/src/PrestaShopBundle/ApiPlatform/Resources'
- '%kernel.project_dir%/tests/Resources/ApiPlatform/Resources'
11 changes: 3 additions & 8 deletions src/Core/Security/OAuth2/TokenAuthenticator.php
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ public function supports(Request $request): bool

public function onAuthenticationFailure(Request $request, AuthenticationException $exception): ?Response
{
return $this->returnWWWAuthenticateResponse();
return $this->returnWWWAuthenticateResponse($exception->getMessage());
}

public function onAuthenticationSuccess(Request $request, TokenInterface $token, string $firewallName): ?Response
Expand All @@ -75,9 +75,9 @@ public function onAuthenticationSuccess(Request $request, TokenInterface $token,
return null;
}

private function returnWWWAuthenticateResponse(): Response
private function returnWWWAuthenticateResponse(?string $content = null): Response
{
return new Response(null, Response::HTTP_UNAUTHORIZED, ['WWW-Authenticate' => 'Bearer']);
return new Response($content, Response::HTTP_UNAUTHORIZED, ['WWW-Authenticate' => 'Bearer']);
}

public function authenticate(Request $request): Passport
Expand All @@ -90,11 +90,6 @@ public function authenticate(Request $request): Passport
throw new CustomUserMessageAuthenticationException('Bearer token missing');
}

$authorization = $request->headers->get('Authorization');
if (null === $authorization) {
throw new CustomUserMessageAuthenticationException('No API token provided');
}

$credentials = $this->httpMessageFactory->createRequest($request);
$userIdentifier = $this->authorizationServer->getUser($credentials);

Expand Down
137 changes: 137 additions & 0 deletions tests/Integration/ApiPlatform/ApiSecurityTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/OSL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to https://devdocs.prestashop.com/ for more information.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
*/

declare(strict_types=1);

namespace Tests\Integration\ApiPlatform;

use Tests\Integration\ApiPlatform\EndPoint\ApiTestCase;
use Tests\Resources\DatabaseDump;

class ApiSecurityTest extends ApiTestCase
{
protected function tearDown(): void
{
parent::tearDown();
DatabaseDump::restoreTables(['api_access']);
}

public function testAuthenticationWithoutScopeSuccess()
{
self::createApiAccess();
$bearerToken = $this->getBearerToken();
$client = static::createClient();
$response = $client->request('GET', '/api/test/unscoped/product/1', [
'headers' => [
'Authorization' => 'Bearer ' . $bearerToken,
],
]);

self::assertResponseStatusCodeSame(200);
$this->assertNotEmpty($response->getContent());
}

public function testAuthenticationWithoutTokenFailed()
{
self::createApiAccess();
$client = static::createClient();
$response = $client->request('GET', '/api/test/unscoped/product/1');

self::assertResponseStatusCodeSame(401);
$this->assertEquals('No Authorization header provided', $response->getContent());
}

public function testAuthenticationWithoutBearerFailed()
{
self::createApiAccess();
$bearerToken = $this->getBearerToken();
$client = static::createClient();
$response = $client->request('GET', '/api/test/unscoped/product/1', [
'headers' => [
'Authorization' => $bearerToken,
],
]);

self::assertResponseStatusCodeSame(401);
$this->assertEquals('Bearer token missing', $response->getContent());
}

public function testAuthenticationWithInvalidCredential()
{
self::createApiAccess();
$client = static::createClient();
$response = $client->request('GET', '/api/test/unscoped/product/1', [
'headers' => [
'Authorization' => 'Bearer toto',
],
]);

self::assertResponseStatusCodeSame(401);
$this->assertEquals('Invalid credentials', $response->getContent());
}


public function testAuthenticationWithLowerCaseBearerFailed()
{
self::createApiAccess();
$bearerToken = $this->getBearerToken();
$client = static::createClient();
$response = $client->request('GET', '/api/test/unscoped/product/1', [
'headers' => [
'Authorization' => 'bearer ' . $bearerToken,
],
]);

self::assertResponseStatusCodeSame(401);
$this->assertEquals('Bearer token missing', $response->getContent());
}

public function testAuthenticationWithScopeSuccess()
{
self::createApiAccess(['product_read']);
$bearerToken = $this->getBearerToken(['product_read']);
$client = static::createClient();
$response = $client->request('GET', '/api/test/scoped/product/1', [
'auth_bearer' => $bearerToken,
]);

self::assertResponseStatusCodeSame(200);
$this->assertNotEmpty($response->getContent());
}

public function testAuthenticationWithScopeFailed()
{
self::createApiAccess();
$bearerToken = $this->getBearerToken();
$client = static::createClient();
$response = $client->request('GET', '/api/test/scoped/product/1', [
'auth_bearer' => $bearerToken,
]);

self::assertResponseStatusCodeSame(403);
$this->assertEmpty($response->getContent());
}
}
54 changes: 54 additions & 0 deletions tests/Resources/ApiPlatform/Resources/ApiTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/OSL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to https://devdocs.prestashop.com/ for more information.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
*/

declare(strict_types=1);

namespace Tests\Resources\ApiPlatform\Resources;

use ApiPlatform\Metadata\ApiResource;
use PrestaShop\Module\APIResources\ApiPlatform\Resources\Product;
use PrestaShop\PrestaShop\Core\Domain\Product\Query\GetProductForEditing;
use PrestaShopBundle\ApiPlatform\Metadata\CQRSGet;

#[ApiResource(
operations: [
new CQRSGet(
uriTemplate: '/test/unscoped/product/{productId}',
CQRSQuery: GetProductForEditing::class,
scopes: [],
CQRSQueryMapping: Product::QUERY_MAPPING,
),
new CQRSGet(
uriTemplate: '/test/scoped/product/{productId}',
CQRSQuery: GetProductForEditing::class,
scopes: ['product_read'],
CQRSQueryMapping: Product::QUERY_MAPPING,
),
],
)]
class ApiTest extends Product
{
}

0 comments on commit 5a97714

Please sign in to comment.