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
|
||||
|
||||
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
|
||||
<IfModule mod_env.c>
|
||||
@ -115,6 +116,15 @@ Switch your app environment to development in `public/.htaccess` file:
|
||||
</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
|
||||
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)
|
||||
|
@ -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
|
||||
*
|
||||
|
@ -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';
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
<IfModule mod_env.c>
|
||||
@ -98,6 +99,15 @@ Switch your app environment to development in `public/.htaccess` file:
|
||||
</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
|
||||
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:
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
*
|
||||
|
@ -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';
|
||||
|
Loading…
x
Reference in New Issue
Block a user