Skip to content

Commit bd0e929

Browse files
toitzisoyuka
andauthoredDec 13, 2024··
feat(openapi): HTTP Authentication Support for Swagger UI (#6665)
* feat(openapi): http authentication support add support for http authentication (for example http basic or bearer tokens) Closes: #6664 * add symfony support --------- Co-authored-by: soyuka <soyuka@users.noreply.github.com>
1 parent c78ed0b commit bd0e929

File tree

10 files changed

+72
-1
lines changed

10 files changed

+72
-1
lines changed
 

‎src/Laravel/ApiPlatformProvider.php

+1
Original file line numberDiff line numberDiff line change
@@ -753,6 +753,7 @@ public function register(): void
753753
contactEmail: $config->get('api-platform.swagger_ui.contact.email', ''),
754754
licenseName: $config->get('api-platform.swagger_ui.license.name', ''),
755755
licenseUrl: $config->get('api-platform.swagger_ui.license.url', ''),
756+
httpAuth: $config->get('api-platform.swagger_ui.http_auth', []),
756757
);
757758
});
758759

‎src/Laravel/config/api-platform.php

+6
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,12 @@
9898
// 'url' => 'https://www.example.com/support',
9999
// 'email' => 'support@example.com',
100100
//],
101+
//'http_auth' => [
102+
// 'Personal Access Token' => [
103+
// 'scheme' => 'bearer',
104+
// 'bearerFormat' => 'JWT'
105+
// ]
106+
//]
101107
],
102108

103109
'url_generation_strategy' => UrlGeneratorInterface::ABS_PATH,

‎src/OpenApi/Factory/OpenApiFactory.php

+5
Original file line numberDiff line numberDiff line change
@@ -744,6 +744,11 @@ private function getSecuritySchemes(): array
744744
$securitySchemes[$key] = new SecurityScheme('apiKey', $description, $apiKey['name'], $apiKey['type']);
745745
}
746746

747+
foreach ($this->openApiOptions->getHttpAuth() as $key => $httpAuth) {
748+
$description = \sprintf('Value for the http %s parameter.', $httpAuth['scheme']);
749+
$securitySchemes[$key] = new SecurityScheme('http', $description, null, null, $httpAuth['scheme'], $httpAuth['bearerFormat'] ?? null);
750+
}
751+
747752
return $securitySchemes;
748753
}
749754

‎src/OpenApi/Options.php

+6-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515

1616
final class Options
1717
{
18-
public function __construct(private readonly string $title, private readonly string $description = '', private readonly string $version = '', private readonly bool $oAuthEnabled = false, private readonly ?string $oAuthType = null, private readonly ?string $oAuthFlow = null, private readonly ?string $oAuthTokenUrl = null, private readonly ?string $oAuthAuthorizationUrl = null, private readonly ?string $oAuthRefreshUrl = null, private readonly array $oAuthScopes = [], private readonly array $apiKeys = [], private readonly ?string $contactName = null, private readonly ?string $contactUrl = null, private readonly ?string $contactEmail = null, private readonly ?string $termsOfService = null, private readonly ?string $licenseName = null, private readonly ?string $licenseUrl = null, private bool $overrideResponses = true)
18+
public function __construct(private readonly string $title, private readonly string $description = '', private readonly string $version = '', private readonly bool $oAuthEnabled = false, private readonly ?string $oAuthType = null, private readonly ?string $oAuthFlow = null, private readonly ?string $oAuthTokenUrl = null, private readonly ?string $oAuthAuthorizationUrl = null, private readonly ?string $oAuthRefreshUrl = null, private readonly array $oAuthScopes = [], private readonly array $apiKeys = [], private readonly ?string $contactName = null, private readonly ?string $contactUrl = null, private readonly ?string $contactEmail = null, private readonly ?string $termsOfService = null, private readonly ?string $licenseName = null, private readonly ?string $licenseUrl = null, private bool $overrideResponses = true, private readonly array $httpAuth = [])
1919
{
2020
}
2121

@@ -74,6 +74,11 @@ public function getApiKeys(): array
7474
return $this->apiKeys;
7575
}
7676

77+
public function getHttpAuth(): array
78+
{
79+
return $this->httpAuth;
80+
}
81+
7782
public function getContactName(): ?string
7883
{
7984
return $this->contactName;

‎src/OpenApi/Tests/Factory/OpenApiFactoryTest.php

+12
Original file line numberDiff line numberDiff line change
@@ -521,6 +521,14 @@ public function testInvoke(): void
521521
'type' => 'query',
522522
'name' => 'key',
523523
],
524+
], null, null, null, null, null, null, true, [
525+
'bearer' => [
526+
'scheme' => 'bearer',
527+
'bearerFormat' => 'JWT',
528+
],
529+
'basic' => [
530+
'scheme' => 'basic',
531+
],
524532
]),
525533
new PaginationOptions(true, 'page', true, 'itemsPerPage', true, 'pagination')
526534
);
@@ -622,12 +630,16 @@ public function testInvoke(): void
622630
'oauth' => new SecurityScheme('oauth2', 'OAuth 2.0 authorization code Grant', null, null, null, null, new OAuthFlows(null, null, null, new OAuthFlow('/oauth/v2/auth', '/oauth/v2/token', '/oauth/v2/refresh', new \ArrayObject(['scope param'])))),
623631
'header' => new SecurityScheme('apiKey', 'Value for the Authorization header parameter.', 'Authorization', 'header'),
624632
'query' => new SecurityScheme('apiKey', 'Value for the key query parameter.', 'key', 'query'),
633+
'bearer' => new SecurityScheme('http', 'Value for the http bearer parameter.', null, null, 'bearer', 'JWT'),
634+
'basic' => new SecurityScheme('http', 'Value for the http basic parameter.', null, null, 'basic', null),
625635
]));
626636

627637
$this->assertEquals([
628638
['oauth' => []],
629639
['header' => []],
630640
['query' => []],
641+
['bearer' => []],
642+
['basic' => []],
631643
], $openApi->getSecurity());
632644

633645
$paths = $openApi->getPaths();

‎src/Symfony/Bundle/DependencyInjection/ApiPlatformExtension.php

+1
Original file line numberDiff line numberDiff line change
@@ -500,6 +500,7 @@ private function registerSwaggerConfiguration(ContainerBuilder $container, array
500500
$container->setParameter('api_platform.enable_swagger_ui', $config['enable_swagger_ui']);
501501
$container->setParameter('api_platform.enable_re_doc', $config['enable_re_doc']);
502502
$container->setParameter('api_platform.swagger.api_keys', $config['swagger']['api_keys']);
503+
$container->setParameter('api_platform.swagger.http_auth', $config['swagger']['http_auth']);
503504
if ($config['openapi']['swagger_ui_extra_configuration'] && $config['swagger']['swagger_ui_extra_configuration']) {
504505
throw new RuntimeException('You can not set "swagger_ui_extra_configuration" twice - in "openapi" and "swagger" section.');
505506
}

‎src/Symfony/Bundle/DependencyInjection/Configuration.php

+18
Original file line numberDiff line numberDiff line change
@@ -330,6 +330,24 @@ private function addSwaggerSection(ArrayNodeDefinition $rootNode): void
330330
->end()
331331
->end()
332332
->end()
333+
->arrayNode('http_auth')
334+
->info('Creates http security schemes for OpenAPI.')
335+
->useAttributeAsKey('key')
336+
->validate()
337+
->ifTrue(static fn ($v): bool => (bool) array_filter(array_keys($v), fn ($item) => !preg_match('/^[a-zA-Z0-9._-]+$/', $item)))
338+
->thenInvalid('The api keys "key" is not valid according to the pattern enforced by OpenAPI 3.1 ^[a-zA-Z0-9._-]+$.')
339+
->end()
340+
->prototype('array')
341+
->children()
342+
->scalarNode('scheme')
343+
->info('The OpenAPI HTTP auth scheme, for example "bearer"')
344+
->end()
345+
->scalarNode('bearerFormat')
346+
->info('The OpenAPI HTTP bearer format')
347+
->end()
348+
->end()
349+
->end()
350+
->end()
333351
->variableNode('swagger_ui_extra_configuration')
334352
->defaultValue([])
335353
->validate()

‎src/Symfony/Bundle/Resources/config/openapi.xml

+1
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@
5959
<argument>%api_platform.openapi.license.name%</argument>
6060
<argument>%api_platform.openapi.license.url%</argument>
6161
<argument>%api_platform.openapi.overrideResponses%</argument>
62+
<argument>%api_platform.swagger.http_auth%</argument>
6263
</service>
6364
<service id="ApiPlatform\OpenApi\Options" alias="api_platform.openapi.options" />
6465

‎src/Symfony/Tests/Bundle/DependencyInjection/ApiPlatformExtensionTest.php

+1
Original file line numberDiff line numberDiff line change
@@ -284,5 +284,6 @@ public function testEventListenersConfiguration(): void
284284
];
285285

286286
$this->assertContainerHas($services, $aliases);
287+
$this->container->hasParameter('api_platform.swagger.http_auth');
287288
}
288289
}

‎tests/Symfony/Bundle/DependencyInjection/ConfigurationTest.php

+21
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,7 @@ private function runDefaultConfigTests(array $doctrineIntegrationsToLoad = ['orm
149149
'swagger' => [
150150
'versions' => [3],
151151
'api_keys' => [],
152+
'http_auth' => [],
152153
'swagger_ui_extra_configuration' => [],
153154
],
154155
'eager_loading' => [
@@ -391,4 +392,24 @@ public function testEnableElasticsearch(): void
391392

392393
$this->assertTrue($config['elasticsearch']['enabled']);
393394
}
395+
396+
/**
397+
* Test config for http auth.
398+
*/
399+
public function testHttpAuth(): void
400+
{
401+
$config = $this->processor->processConfiguration($this->configuration, [
402+
'api_platform' => [
403+
'swagger' => [
404+
'http_auth' => ['PAT' => [
405+
'scheme' => 'bearer',
406+
'bearerFormat' => 'JWT',
407+
]],
408+
],
409+
],
410+
]);
411+
412+
$this->assertArrayHasKey('http_auth', $config['swagger']);
413+
$this->assertSame(['scheme' => 'bearer', 'bearerFormat' => 'JWT'], $config['swagger']['http_auth']['PAT']);
414+
}
394415
}

0 commit comments

Comments
 (0)
Please sign in to comment.