Skip to content

🐛 open api security schemes #134

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Aug 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
104 changes: 85 additions & 19 deletions config/rest.php
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,8 @@
],
'info' => [
'title' => config('app.name'),
'summary' => 'This is my projet\'s documentation',
'description' => 'Find out all about my projet\'s API',
'summary' => 'This is my project\'s documentation',
'description' => 'Find out all about my project\'s API',
'termsOfService' => null, // (Optional) Url to terms of services
'contact' => [
'name' => 'My Company',
Expand Down Expand Up @@ -103,23 +103,89 @@
],
// See https://spec.openapis.org/oas/v3.1.0#security-scheme-object
'security' => [
// [
// 'type' => 'http',
// 'description' => 'description',
// 'scheme' => 'Bearer',
// 'bearerFormat' => 'JWT'
// ],
// [
// 'type' => 'oauth2',
// 'flows' => [
// 'authorizationCode' => [
// 'scopes' => ['write:pets'],
// 'tokenUrl' => 'https://example.com/api/oauth/token',
// 'authorizationUrl' => 'https://example.com/api/oauth/dialog',
// 'refreshUrl' => 'https://example.com/api/oauth/refresh',
// ]
// ]
// ]
// [
// "api_key" => []
// ],
// [
// "auth" => [
// 'write:users',
// 'read:users'
// ]
// ]
],
// See https://spec.openapis.org/oas/v3.1.0#security-scheme-object
'securitySchemes' => [
// "api_key" => [
// "description" => "Authentication via API key",
// "type" => "apiKey",
// "name" => "x-api-key",
// "in" => "header"
// ],
// "http_bearer" => [
// "description" => "HTTP authentication with bearer token",
// "type" => "http",
// "scheme" => "bearer",
// "bearerFormat" => "JWT"
// ],
// "oauth_authcode" => [
// "description" => "Authentication via OAuth2 with authorization code flow",
// "type" => "oauth2",
// "flows" => [
// "authorizationCode" => [
// "authorizationUrl" => "https://example.com/api/oauth/dialog",
// "tokenUrl" => "https://example.com/api/oauth/token",
// "refreshUrl" => "https://example.com/api/oauth/refresh",
// "scopes" => [
// "do:something" => "do something"
// ]
// ]
// ]
// ],
// "oauth_clientcredentials" => [
// "description" => "Authentication via OAuth2 with client credentials flow",
// "type" => "oauth2",
// "flows" => [
// "clientCredentials" => [
// "tokenUrl" => "https://example.com/api/oauth/token",
// "refreshUrl" => "https://example.com/api/oauth/refresh",
// "scopes" => [
// "do:something" => "do something"
// ]
// ]
// ]
// ],
// "oauth_implicit" => [
// "description" => "Authentication via OAuth2 with implicit flow",
// "type" => "oauth2",
// "flows" => [
// "implicit" => [
// "authorizationUrl" => "https://example.com/api/oauth/dialog",
// "refreshUrl" => "https://example.com/api/oauth/refresh",
// "scopes" => [
// "write:foo" => "modify foo",
// "read:foo" => "read foo"
// ]
// ]
// ]
// ],
// "oauth_password" => [
// "description" => "Authentication via OAuth2 with resource owner password flow",
// "type" => "oauth2",
// "flows" => [
// "password" => [
// "tokenUrl" => "https://example.com/api/oauth/token",
// "refreshUrl" => "https://example.com/api/oauth/refresh",
// "scopes" => [
// "do:something" => "do something"
// ]
// ]
// ]
// ],
// "open_id" => [
// "description" => "Authentication via OpenID Connect",
// "type" => "openIdConnect",
// "openIdConnectUrl" => "https://example.com/openid/issuer/location"
// ]
],
],
];
69 changes: 52 additions & 17 deletions src/Documentation/Schemas/OpenAPI.php
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,13 @@ class OpenAPI extends Schema
*/
protected array $security = [];

/**
* A declaration of which security schemes mechanisms can be used across the API.
*
* @var array
*/
protected array $securitySchemes = [];

/**
* Get the version number of the OpenAPI specification.
*
Expand Down Expand Up @@ -140,6 +147,30 @@ public function withSecurity(array $security): self
return $this;
}

/**
* Get the declaration of security mechanisms for the API.
*
* @return array
*/
public function securitySchemes(): array
{
return $this->securitySchemes;
}

/**
* Set the declaration of security mechanisms for the API.
*
* @param array $securitySchemes
*
* @return self
*/
public function withSecuritySchemes(array $securitySchemes): self
{
$this->securitySchemes = $securitySchemes;

return $this;
}

/**
* Set the Server Objects, which provide connectivity information to a target server.
*
Expand Down Expand Up @@ -178,7 +209,10 @@ public function jsonSerialize(): mixed
'paths' => collect($this->paths())->map->jsonSerialize()->toArray(),
],
isset($this->servers) ? ['servers' => collect($this->servers())->map->jsonSerialize()->toArray()] : [],
isset($this->security) ? ['security' => collect($this->security())->map->jsonSerialize()->toArray()] : []
isset($this->security) ? ['security' => $this->security] : [],
['components' => array_merge(
isset($this->securitySchemes) ? ['securitySchemes' => collect($this->securitySchemes())->map->jsonSerialize()->toArray()] : []
)]
);
}

Expand Down Expand Up @@ -207,30 +241,30 @@ public function generate(): OpenAPI
$servers[] = $serverInstance;
}

$securities = [];

foreach (config('rest.documentation.security') as $security) {
$securityInstance = (new SecurityScheme())
->withDescription($security['description'] ?? '')
->withIn($security['in'] ?? '')
->withType($security['type'] ?? '')
->withName($security['name'] ?? '')
->withBearerFormat($security['bearerFormat'] ?? '')
->withOpenIdConnectUrl($security['openIdConnectUrl'] ?? '')
->withScheme($security['scheme'] ?? '')
$securitySchemes = [];

foreach (config('rest.documentation.securitySchemes') as $securitySchemeKey => $securityScheme) {
$securitySchemeInstance = (new SecurityScheme())
->withDescription($securityScheme['description'] ?? '')
->withIn($securityScheme['in'] ?? '')
->withType($securityScheme['type'] ?? '')
->withName($securityScheme['name'] ?? '')
->withBearerFormat($securityScheme['bearerFormat'] ?? '')
->withOpenIdConnectUrl($securityScheme['openIdConnectUrl'] ?? '')
->withScheme($securityScheme['scheme'] ?? '')
->withFlows($oauthFlows = new OauthFlows());

foreach ($security['flows'] ?? [] as $key => $flow) {
foreach ($securityScheme['flows'] ?? [] as $key => $flow) {
$flowInstance = (new OauthFlow())
->withScopes($flow['scopes'] ?? [])
->withAuthorizationUrl($flow['authorizationUrl'] ?? '')
->withTokenUrl($flow['tokenUrl'])
->withRefreshUrl($flow['refreshUrl']);
->withTokenUrl($flow['tokenUrl'] ?? '')
->withRefreshUrl($flow['refreshUrl'] ?? '');

$oauthFlows->{'with'.Str::studly($key)}($flowInstance);
}

$securities[] = $securityInstance;
$securitySchemes[$securitySchemeKey] = $securitySchemeInstance;
}

return Rest::applyDocumentationCallback(
Expand All @@ -242,7 +276,8 @@ public function generate(): OpenAPI
->withPaths(
$this->generatePaths()
)
->withSecurity($securities)
->withSecuritySchemes($securitySchemes)
->withSecurity(config('rest.documentation.security'))
->withServers($servers)
);
}
Expand Down