forked from loafle/openapi-generator-original
* fix: added middleware adding for authorization methods, added unauthorized handler to authorization abstract, fixes #18031 * feat: updated generated sample for php-slim4 * fix: small fix for running error handlers and environment setting fix * feat: removed unused dependency in abstract authenticator, php-slim4
This commit is contained in:
parent
5e9546451c
commit
f258ce2cf5
@ -107,7 +107,8 @@ $ composer phplint
|
|||||||
|
|
||||||
## Show errors
|
## 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
|
```ini
|
||||||
## .htaccess
|
## .htaccess
|
||||||
<IfModule mod_env.c>
|
<IfModule mod_env.c>
|
||||||
@ -115,6 +116,15 @@ Switch your app environment to development in `public/.htaccess` file:
|
|||||||
</IfModule>
|
</IfModule>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
- 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
|
## 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.
|
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:
|
CURL example:
|
||||||
@ -214,6 +224,11 @@ Scope list:
|
|||||||
{{/scopes}}
|
{{/scopes}}
|
||||||
|
|
||||||
{{/isOAuth}}
|
{{/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}}
|
{{/authMethods}}
|
||||||
### Advanced middleware configuration
|
### Advanced middleware configuration
|
||||||
Ref to used Slim Token Middleware [dyorg/slim-token-authentication](https://github.com/dyorg/slim-token-authentication/tree/1.x#readme)
|
Ref to used Slim Token Middleware [dyorg/slim-token-authentication](https://github.com/dyorg/slim-token-authentication/tree/1.x#readme)
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
namespace {{authPackage}};
|
namespace {{authPackage}};
|
||||||
|
|
||||||
use Psr\Http\Message\ServerRequestInterface;
|
use Psr\Http\Message\ServerRequestInterface;
|
||||||
use Dyorg\TokenAuthentication;
|
use Psr\Http\Message\ResponseInterface;
|
||||||
use Dyorg\TokenAuthentication\TokenSearch;
|
use Dyorg\TokenAuthentication\TokenSearch;
|
||||||
use Dyorg\TokenAuthentication\Exceptions\UnauthorizedExceptionInterface;
|
use Dyorg\TokenAuthentication\Exceptions\UnauthorizedExceptionInterface;
|
||||||
|
|
||||||
@ -39,6 +39,32 @@ abstract class {{abstractNamePrefix}}Authenticator{{abstractNameSuffix}}
|
|||||||
*/
|
*/
|
||||||
abstract protected function getUserByToken(string $token);
|
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
|
* Authenticator constructor
|
||||||
*
|
*
|
||||||
|
@ -25,7 +25,7 @@ $builder = new ContainerBuilder();
|
|||||||
|
|
||||||
// consider prod by default
|
// consider prod by default
|
||||||
$env;
|
$env;
|
||||||
switch (strtolower($_SERVER['APP_ENV'] ?? 'prod')) {
|
switch (strtolower($_SERVER['APP_ENV'] ?? getenv('APP_ENV') ?? 'prod')) {
|
||||||
case 'development':
|
case 'development':
|
||||||
case 'dev':
|
case 'dev':
|
||||||
$env = 'dev';
|
$env = 'dev';
|
||||||
|
@ -14,6 +14,23 @@ namespace {{appPackage}};
|
|||||||
use Psr\Http\Message\ResponseInterface;
|
use Psr\Http\Message\ResponseInterface;
|
||||||
use Psr\Http\Message\ServerRequestInterface;
|
use Psr\Http\Message\ServerRequestInterface;
|
||||||
use Slim\Exception\HttpNotImplementedException;
|
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
|
* RegisterRoutes Class Doc Comment
|
||||||
@ -60,7 +77,9 @@ class RegisterRoutes
|
|||||||
{{#isBasicBearer}}
|
{{#isBasicBearer}}
|
||||||
[
|
[
|
||||||
'type' => '{{type}}',
|
'type' => '{{type}}',
|
||||||
'isBasic' => true,
|
'scheme' => '{{scheme}}',
|
||||||
|
'bearerFormat' => '{{bearerFormat}}',
|
||||||
|
'isBasic' => false,
|
||||||
'isBearer' => true,
|
'isBearer' => true,
|
||||||
'isApiKey' => false,
|
'isApiKey' => false,
|
||||||
'isOAuth' => false,
|
'isOAuth' => false,
|
||||||
@ -152,6 +171,93 @@ class RegisterRoutes
|
|||||||
$callback
|
$callback
|
||||||
)->setName($operation['operationId']);
|
)->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) {
|
foreach ($middlewares as $middleware) {
|
||||||
$route->add($middleware);
|
$route->add($middleware);
|
||||||
}
|
}
|
||||||
|
@ -90,7 +90,8 @@ $ composer phplint
|
|||||||
|
|
||||||
## Show errors
|
## 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
|
```ini
|
||||||
## .htaccess
|
## .htaccess
|
||||||
<IfModule mod_env.c>
|
<IfModule mod_env.c>
|
||||||
@ -98,6 +99,15 @@ Switch your app environment to development in `public/.htaccess` file:
|
|||||||
</IfModule>
|
</IfModule>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
- 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
|
## 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.
|
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:
|
CURL example:
|
||||||
|
@ -27,6 +27,9 @@ namespace OpenAPIServer\App;
|
|||||||
use Psr\Http\Message\ResponseInterface;
|
use Psr\Http\Message\ResponseInterface;
|
||||||
use Psr\Http\Message\ServerRequestInterface;
|
use Psr\Http\Message\ServerRequestInterface;
|
||||||
use Slim\Exception\HttpNotImplementedException;
|
use Slim\Exception\HttpNotImplementedException;
|
||||||
|
use Dyorg\TokenAuthentication;
|
||||||
|
use OpenAPIServer\Auth\OAuthAuthenticator;
|
||||||
|
use OpenAPIServer\Auth\ApiKeyAuthenticator;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* RegisterRoutes Class Doc Comment
|
* RegisterRoutes Class Doc Comment
|
||||||
@ -881,6 +884,55 @@ class RegisterRoutes
|
|||||||
$callback
|
$callback
|
||||||
)->setName($operation['operationId']);
|
)->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) {
|
foreach ($middlewares as $middleware) {
|
||||||
$route->add($middleware);
|
$route->add($middleware);
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,7 @@
|
|||||||
namespace OpenAPIServer\Auth;
|
namespace OpenAPIServer\Auth;
|
||||||
|
|
||||||
use Psr\Http\Message\ServerRequestInterface;
|
use Psr\Http\Message\ServerRequestInterface;
|
||||||
use Dyorg\TokenAuthentication;
|
use Psr\Http\Message\ResponseInterface;
|
||||||
use Dyorg\TokenAuthentication\TokenSearch;
|
use Dyorg\TokenAuthentication\TokenSearch;
|
||||||
use Dyorg\TokenAuthentication\Exceptions\UnauthorizedExceptionInterface;
|
use Dyorg\TokenAuthentication\Exceptions\UnauthorizedExceptionInterface;
|
||||||
|
|
||||||
@ -52,6 +52,32 @@ abstract class AbstractAuthenticator
|
|||||||
*/
|
*/
|
||||||
abstract protected function getUserByToken(string $token);
|
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
|
* Authenticator constructor
|
||||||
*
|
*
|
||||||
|
@ -37,7 +37,7 @@ $builder = new ContainerBuilder();
|
|||||||
|
|
||||||
// consider prod by default
|
// consider prod by default
|
||||||
$env;
|
$env;
|
||||||
switch (strtolower($_SERVER['APP_ENV'] ?? 'prod')) {
|
switch (strtolower($_SERVER['APP_ENV'] ?? getenv('APP_ENV') ?? 'prod')) {
|
||||||
case 'development':
|
case 'development':
|
||||||
case 'dev':
|
case 'dev':
|
||||||
$env = 'dev';
|
$env = 'dev';
|
||||||
|
Loading…
x
Reference in New Issue
Block a user