diff --git a/modules/openapi-generator/src/main/resources/php-slim4-server/README.mustache b/modules/openapi-generator/src/main/resources/php-slim4-server/README.mustache
index c0df2c5baa2..dd5fb253184 100644
--- a/modules/openapi-generator/src/main/resources/php-slim4-server/README.mustache
+++ b/modules/openapi-generator/src/main/resources/php-slim4-server/README.mustache
@@ -107,7 +107,8 @@ $ composer phplint
## Show errors
-Switch your app environment to development in `public/.htaccess` file:
+Switch your app environment to development
+- When using with some webserver => in `public/.htaccess` file:
```ini
## .htaccess
@@ -115,6 +116,15 @@ Switch your app environment to development in `public/.htaccess` file:
```
+- Or when using whatever else, set `APP_ENV` environment variable like this:
+```bash
+export APP_ENV=development
+```
+or simply
+```bash
+export APP_ENV=dev
+```
+
## Mock Server
Since this feature should be used for development only, change environment to `development` and send additional HTTP header `X-{{invokerPackage}}-Mock: ping` with any request to get mocked response.
CURL example:
@@ -214,6 +224,11 @@ Scope list:
{{/scopes}}
{{/isOAuth}}
+{{#isBasicBearer}}
+### Security schema `{{name}}`
+> Important! To make Bearer authentication work you need to extend [\{{authPackage}}\{{abstractNamePrefix}}Authenticator{{abstractNameSuffix}}]({{#lambda.forwardslash}}{{authSrcPath}}{{/lambda.forwardslash}}/{{abstractNamePrefix}}Authenticator{{abstractNameSuffix}}.php) class by [\{{authPackage}}\BearerAuthenticator](./src/Auth/BearerAuthenticator.php) class.
+
+{{/isBasicBearer}}
{{/authMethods}}
### Advanced middleware configuration
Ref to used Slim Token Middleware [dyorg/slim-token-authentication](https://github.com/dyorg/slim-token-authentication/tree/1.x#readme)
diff --git a/modules/openapi-generator/src/main/resources/php-slim4-server/abstract_authenticator.mustache b/modules/openapi-generator/src/main/resources/php-slim4-server/abstract_authenticator.mustache
index 3aef910d9f1..af20a196704 100644
--- a/modules/openapi-generator/src/main/resources/php-slim4-server/abstract_authenticator.mustache
+++ b/modules/openapi-generator/src/main/resources/php-slim4-server/abstract_authenticator.mustache
@@ -10,7 +10,7 @@
namespace {{authPackage}};
use Psr\Http\Message\ServerRequestInterface;
-use Dyorg\TokenAuthentication;
+use Psr\Http\Message\ResponseInterface;
use Dyorg\TokenAuthentication\TokenSearch;
use Dyorg\TokenAuthentication\Exceptions\UnauthorizedExceptionInterface;
@@ -39,6 +39,32 @@ abstract class {{abstractNamePrefix}}Authenticator{{abstractNameSuffix}}
*/
abstract protected function getUserByToken(string $token);
+ /**
+ * Handles the response for unauthorized access attempts.
+ *
+ * This method is called when an access token is either not provided, invalid, or expired.
+ * It constructs a response that includes an error message, the status code, and any other relevant information.
+ *
+ * @param ServerRequestInterface $request The HTTP request that led to the unauthorized access attempt.
+ * @param ResponseInterface $response The response object that will be modified to reflect the unauthorized status.
+ * @param UnauthorizedExceptionInterface $exception The exception triggered due to unauthorized access, containing details such as the error message.
+ *
+ * @return ResponseInterface The modified response object with the unauthorized access error information, including a 401 status code and a JSON body with the error message and token information.
+ */
+ public static function handleUnauthorized(ServerRequestInterface $request, ResponseInterface $response, UnauthorizedExceptionInterface $exception)
+ {
+ $output = [
+ 'message' => $exception->getMessage(),
+ 'token' => $request->getAttribute('authorization_token'),
+ 'success' => false
+ ];
+
+ $response->getBody()->write(json_encode($output));
+ return $response
+ ->withHeader('Content-Type', 'application/json')
+ ->withStatus(401);
+ }
+
/**
* Authenticator constructor
*
diff --git a/modules/openapi-generator/src/main/resources/php-slim4-server/index.mustache b/modules/openapi-generator/src/main/resources/php-slim4-server/index.mustache
index 18f2574b24b..305ea12cf4c 100644
--- a/modules/openapi-generator/src/main/resources/php-slim4-server/index.mustache
+++ b/modules/openapi-generator/src/main/resources/php-slim4-server/index.mustache
@@ -25,7 +25,7 @@ $builder = new ContainerBuilder();
// consider prod by default
$env;
-switch (strtolower($_SERVER['APP_ENV'] ?? 'prod')) {
+switch (strtolower($_SERVER['APP_ENV'] ?? getenv('APP_ENV') ?? 'prod')) {
case 'development':
case 'dev':
$env = 'dev';
diff --git a/modules/openapi-generator/src/main/resources/php-slim4-server/register_routes.mustache b/modules/openapi-generator/src/main/resources/php-slim4-server/register_routes.mustache
index 8b1cbf98ada..abaf5d09f4b 100644
--- a/modules/openapi-generator/src/main/resources/php-slim4-server/register_routes.mustache
+++ b/modules/openapi-generator/src/main/resources/php-slim4-server/register_routes.mustache
@@ -14,6 +14,23 @@ namespace {{appPackage}};
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Slim\Exception\HttpNotImplementedException;
+{{#hasAuthMethods}}
+use Dyorg\TokenAuthentication;
+ {{#authMethods}}
+ {{#isBasicBasic}}
+use {{authPackage}}\BasicAuthenticator;
+ {{/isBasicBasic}}
+ {{#isApiKey}}
+use {{authPackage}}\ApiKeyAuthenticator;
+ {{/isApiKey}}
+ {{#isOAuth}}
+use {{authPackage}}\OAuthAuthenticator;
+ {{/isOAuth}}
+ {{#isBasicBearer}}
+use {{authPackage}}\BearerAuthenticator;
+ {{/isBasicBearer}}
+ {{/authMethods}}
+{{/hasAuthMethods}}
/**
* RegisterRoutes Class Doc Comment
@@ -60,7 +77,9 @@ class RegisterRoutes
{{#isBasicBearer}}
[
'type' => '{{type}}',
- 'isBasic' => true,
+ 'scheme' => '{{scheme}}',
+ 'bearerFormat' => '{{bearerFormat}}',
+ 'isBasic' => false,
'isBearer' => true,
'isApiKey' => false,
'isOAuth' => false,
@@ -152,6 +171,93 @@ class RegisterRoutes
$callback
)->setName($operation['operationId']);
+ {{#hasAuthMethods}}
+ // Add authentication middleware based on the operation's authMethods
+ if ($operation['authMethods']) {
+ foreach ($operation['authMethods'] as $authMethod) {
+ {{#authMethods}}
+ {{#isBasicBasic}}
+ if ($authMethod['isBasic']) {
+ $route->add(new TokenAuthentication([
+ 'path' => '/',
+ 'authenticator' => new BasicAuthenticator,
+ 'regex' => '/Basic\s+(.*)$/i',
+ 'header' => 'Authorization',
+ 'parameter' => null,
+ 'cookie' => null,
+ 'argument' => null,
+ 'attribute' => 'authorization_token',
+ 'error' => ['{{authPackage}}\BasicAuthenticator', 'handleUnauthorized'],
+ ]));
+ }
+ {{/isBasicBasic}}
+ {{#isApiKey}}
+ if ($authMethod['isApiKey']) {
+ $authenticatorConfig = [
+ 'path' => '/',
+ 'authenticator' => new ApiKeyAuthenticator,
+ 'regex' => '/\s+(.*)$/i',
+ 'argument' => null,
+ 'attribute' => 'authorization_token',
+ 'error' => ['{{authPackage}}\ApiKeyAuthenticator', 'handleUnauthorized'],
+ ];
+ if ($authMethod['isKeyInHeader']) {
+ $authenticatorConfig = [
+ 'header' => $authMethod['keyParamName'],
+ 'parameter' => null,
+ 'cookie' => null,
+ ]
+ } else if ($authMethod['isKeyInQuery']) {
+ $authenticatorConfig = [
+ 'header' => null,
+ 'parameter' => $authMethod['keyParamName'],
+ 'cookie' => null,
+ ]
+ } else if ($authMethod['isKeyInCookie']) {
+ $authenticatorConfig = [
+ 'header' => null,
+ 'parameter' => null,
+ 'cookie' => $authMethod['keyParamName'],
+ ]
+ }
+ $route->add(new TokenAuthentication($authenticatorConfig));
+ }
+ {{/isApiKey}}
+ {{#isBasicBearer}}
+ if ($authMethod['isBearer']) {
+ $route->add(new TokenAuthentication([
+ 'path' => '/',
+ 'authenticator' => new BearerAuthenticator,
+ 'regex' => '/Bearer\s+(.*)$/i',
+ 'header' => 'Authorization',
+ 'parameter' => null,
+ 'cookie' => null,
+ 'argument' => null,
+ 'attribute' => 'authorization_token',
+ 'error' => ['{{authPackage}}\BearerAuthenticator', 'handleUnauthorized'],
+ ]));
+ }
+ {{/isBasicBearer}}
+ {{#isOAuth}}
+ if ($authMethod['isOAuth']) {
+ $route->add(new TokenAuthentication([
+ 'path' => '/',
+ 'authenticator' => new OAuthAuthenticator($authMethod['scopes']),
+ 'regex' => '/Bearer\s+(.*)$/i',
+ 'header' => 'Authorization',
+ 'parameter' => null,
+ 'cookie' => null,
+ 'argument' => null,
+ 'attribute' => 'authorization_token',
+ 'error' => ['{{authPackage}}\OAuthAuthenticator', 'handleUnauthorized'],
+ ]));
+ }
+ {{/isOAuth}}
+ {{/authMethods}}
+ }
+ }
+ {{/hasAuthMethods}}
+
foreach ($middlewares as $middleware) {
$route->add($middleware);
}
diff --git a/samples/server/petstore/php-slim4/README.md b/samples/server/petstore/php-slim4/README.md
index e5dc584f80c..f1d568cc757 100644
--- a/samples/server/petstore/php-slim4/README.md
+++ b/samples/server/petstore/php-slim4/README.md
@@ -90,7 +90,8 @@ $ composer phplint
## Show errors
-Switch your app environment to development in `public/.htaccess` file:
+Switch your app environment to development
+- When using with some webserver => in `public/.htaccess` file:
```ini
## .htaccess
@@ -98,6 +99,15 @@ Switch your app environment to development in `public/.htaccess` file:
```
+- Or when using whatever else, set `APP_ENV` environment variable like this:
+```bash
+export APP_ENV=development
+```
+or simply
+```bash
+export APP_ENV=dev
+```
+
## Mock Server
Since this feature should be used for development only, change environment to `development` and send additional HTTP header `X-OpenAPIServer-Mock: ping` with any request to get mocked response.
CURL example:
diff --git a/samples/server/petstore/php-slim4/lib/App/RegisterRoutes.php b/samples/server/petstore/php-slim4/lib/App/RegisterRoutes.php
index 0c719abdfb9..fae7317d455 100644
--- a/samples/server/petstore/php-slim4/lib/App/RegisterRoutes.php
+++ b/samples/server/petstore/php-slim4/lib/App/RegisterRoutes.php
@@ -27,6 +27,9 @@ namespace OpenAPIServer\App;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Slim\Exception\HttpNotImplementedException;
+use Dyorg\TokenAuthentication;
+use OpenAPIServer\Auth\OAuthAuthenticator;
+use OpenAPIServer\Auth\ApiKeyAuthenticator;
/**
* RegisterRoutes Class Doc Comment
@@ -881,6 +884,55 @@ class RegisterRoutes
$callback
)->setName($operation['operationId']);
+ // Add authentication middleware based on the operation's authMethods
+ if ($operation['authMethods']) {
+ foreach ($operation['authMethods'] as $authMethod) {
+ if ($authMethod['isOAuth']) {
+ $route->add(new TokenAuthentication([
+ 'path' => '/',
+ 'authenticator' => new OAuthAuthenticator($authMethod['scopes']),
+ 'regex' => '/Bearer\s+(.*)$/i',
+ 'header' => 'Authorization',
+ 'parameter' => null,
+ 'cookie' => null,
+ 'argument' => null,
+ 'attribute' => 'authorization_token',
+ 'error' => ['OpenAPIServer\Auth\OAuthAuthenticator', 'handleUnauthorized'],
+ ]));
+ }
+ if ($authMethod['isApiKey']) {
+ $authenticatorConfig = [
+ 'path' => '/',
+ 'authenticator' => new ApiKeyAuthenticator,
+ 'regex' => '/\s+(.*)$/i',
+ 'argument' => null,
+ 'attribute' => 'authorization_token',
+ 'error' => ['OpenAPIServer\Auth\ApiKeyAuthenticator', 'handleUnauthorized'],
+ ];
+ if ($authMethod['isKeyInHeader']) {
+ $authenticatorConfig = [
+ 'header' => $authMethod['keyParamName'],
+ 'parameter' => null,
+ 'cookie' => null,
+ ]
+ } else if ($authMethod['isKeyInQuery']) {
+ $authenticatorConfig = [
+ 'header' => null,
+ 'parameter' => $authMethod['keyParamName'],
+ 'cookie' => null,
+ ]
+ } else if ($authMethod['isKeyInCookie']) {
+ $authenticatorConfig = [
+ 'header' => null,
+ 'parameter' => null,
+ 'cookie' => $authMethod['keyParamName'],
+ ]
+ }
+ $route->add(new TokenAuthentication($authenticatorConfig));
+ }
+ }
+ }
+
foreach ($middlewares as $middleware) {
$route->add($middleware);
}
diff --git a/samples/server/petstore/php-slim4/lib/Auth/AbstractAuthenticator.php b/samples/server/petstore/php-slim4/lib/Auth/AbstractAuthenticator.php
index 699fd1fdbc7..b253a0f84bb 100644
--- a/samples/server/petstore/php-slim4/lib/Auth/AbstractAuthenticator.php
+++ b/samples/server/petstore/php-slim4/lib/Auth/AbstractAuthenticator.php
@@ -23,7 +23,7 @@
namespace OpenAPIServer\Auth;
use Psr\Http\Message\ServerRequestInterface;
-use Dyorg\TokenAuthentication;
+use Psr\Http\Message\ResponseInterface;
use Dyorg\TokenAuthentication\TokenSearch;
use Dyorg\TokenAuthentication\Exceptions\UnauthorizedExceptionInterface;
@@ -52,6 +52,32 @@ abstract class AbstractAuthenticator
*/
abstract protected function getUserByToken(string $token);
+ /**
+ * Handles the response for unauthorized access attempts.
+ *
+ * This method is called when an access token is either not provided, invalid, or expired.
+ * It constructs a response that includes an error message, the status code, and any other relevant information.
+ *
+ * @param ServerRequestInterface $request The HTTP request that led to the unauthorized access attempt.
+ * @param ResponseInterface $response The response object that will be modified to reflect the unauthorized status.
+ * @param UnauthorizedExceptionInterface $exception The exception triggered due to unauthorized access, containing details such as the error message.
+ *
+ * @return ResponseInterface The modified response object with the unauthorized access error information, including a 401 status code and a JSON body with the error message and token information.
+ */
+ public static function handleUnauthorized(ServerRequestInterface $request, ResponseInterface $response, UnauthorizedExceptionInterface $exception)
+ {
+ $output = [
+ 'message' => $exception->getMessage(),
+ 'token' => $request->getAttribute('authorization_token'),
+ 'success' => false
+ ];
+
+ $response->getBody()->write(json_encode($output));
+ return $response
+ ->withHeader('Content-Type', 'application/json')
+ ->withStatus(401);
+ }
+
/**
* Authenticator constructor
*
diff --git a/samples/server/petstore/php-slim4/public/index.php b/samples/server/petstore/php-slim4/public/index.php
index 795b85efa0f..1868cac9576 100644
--- a/samples/server/petstore/php-slim4/public/index.php
+++ b/samples/server/petstore/php-slim4/public/index.php
@@ -37,7 +37,7 @@ $builder = new ContainerBuilder();
// consider prod by default
$env;
-switch (strtolower($_SERVER['APP_ENV'] ?? 'prod')) {
+switch (strtolower($_SERVER['APP_ENV'] ?? getenv('APP_ENV') ?? 'prod')) {
case 'development':
case 'dev':
$env = 'dev';