From 5ed6f0ce86de42b56efa31e07097b7556c26b4d1 Mon Sep 17 00:00:00 2001 From: ErickSkrauch <erickskrauch@yandex.ru> Date: Fri, 6 Dec 2024 01:34:09 +0100 Subject: [PATCH] Move OAuth module from API to common and solve PHPStan's errors --- .../OAuth2/Events/RequestedRefreshToken.php | 10 - .../OAuth2/Grants/ClientCredentialsGrant.php | 12 -- .../ResponseTypes/BearerTokenResponse.php | 12 -- api/components/Tokens/TokenReader.php | 3 + api/config/config.php | 3 - .../controllers/AuthorizationController.php | 22 +- api/modules/oauth/models/OauthProcess.php | 43 ++-- api/tests/functional/_steps/OauthSteps.php | 2 +- .../OAuth2/Entities/AccessTokenEntityTest.php | 2 +- autocompletion.php | 1 - .../OAuth2/AuthorizationServerFactory.php | 16 +- .../components/OAuth2/CryptTrait.php | 6 +- .../OAuth2/Entities/AccessTokenEntity.php | 2 +- .../OAuth2/Entities/AuthCodeEntity.php | 4 +- .../OAuth2/Entities/ClientEntity.php | 8 +- .../OAuth2/Entities/ScopeEntity.php | 7 +- .../components/OAuth2/Entities/UserEntity.php | 4 +- .../OAuth2/Events/RequestedRefreshToken.php | 10 + .../OAuth2/Grants/AuthCodeGrant.php | 22 +- .../OAuth2/Grants/ClientCredentialsGrant.php | 12 ++ .../OAuth2/Grants/RefreshTokenGrant.php | 28 +-- .../components/OAuth2/Keys/EmptyKey.php | 4 +- .../Repositories/AccessTokenRepository.php | 21 +- .../Repositories/AuthCodeRepository.php | 10 +- .../OAuth2/Repositories/ClientRepository.php | 17 +- .../Repositories/EmptyScopeRepository.php | 8 +- .../Repositories/InternalScopeRepository.php | 12 +- .../Repositories/PublicScopeRepository.php | 10 +- .../Repositories/RefreshTokenRepository.php | 8 +- .../ResponseTypes/BearerTokenResponse.php | 12 ++ common/config/config.php | 1 + phpstan-baseline.neon | 200 ------------------ 32 files changed, 155 insertions(+), 377 deletions(-) delete mode 100644 api/components/OAuth2/Events/RequestedRefreshToken.php delete mode 100644 api/components/OAuth2/Grants/ClientCredentialsGrant.php delete mode 100644 api/components/OAuth2/ResponseTypes/BearerTokenResponse.php rename api/components/OAuth2/Component.php => common/components/OAuth2/AuthorizationServerFactory.php (82%) rename {api => common}/components/OAuth2/CryptTrait.php (81%) rename {api => common}/components/OAuth2/Entities/AccessTokenEntity.php (93%) rename {api => common}/components/OAuth2/Entities/AuthCodeEntity.php (75%) rename {api => common}/components/OAuth2/Entities/ClientEntity.php (77%) rename {api => common}/components/OAuth2/Entities/ScopeEntity.php (66%) rename {api => common}/components/OAuth2/Entities/UserEntity.php (71%) create mode 100644 common/components/OAuth2/Events/RequestedRefreshToken.php rename {api => common}/components/OAuth2/Grants/AuthCodeGrant.php (69%) create mode 100644 common/components/OAuth2/Grants/ClientCredentialsGrant.php rename {api => common}/components/OAuth2/Grants/RefreshTokenGrant.php (85%) rename {api => common}/components/OAuth2/Keys/EmptyKey.php (76%) rename {api => common}/components/OAuth2/Repositories/AccessTokenRepository.php (63%) rename {api => common}/components/OAuth2/Repositories/AuthCodeRepository.php (57%) rename {api => common}/components/OAuth2/Repositories/ClientRepository.php (61%) rename {api => common}/components/OAuth2/Repositories/EmptyScopeRepository.php (80%) rename {api => common}/components/OAuth2/Repositories/InternalScopeRepository.php (85%) rename {api => common}/components/OAuth2/Repositories/PublicScopeRepository.php (86%) rename {api => common}/components/OAuth2/Repositories/RefreshTokenRepository.php (63%) create mode 100644 common/components/OAuth2/ResponseTypes/BearerTokenResponse.php diff --git a/api/components/OAuth2/Events/RequestedRefreshToken.php b/api/components/OAuth2/Events/RequestedRefreshToken.php deleted file mode 100644 index 337633d..0000000 --- a/api/components/OAuth2/Events/RequestedRefreshToken.php +++ /dev/null @@ -1,10 +0,0 @@ -<?php -declare(strict_types=1); - -namespace api\components\OAuth2\Events; - -use League\OAuth2\Server\EventEmitting\AbstractEvent; - -class RequestedRefreshToken extends AbstractEvent { - -} diff --git a/api/components/OAuth2/Grants/ClientCredentialsGrant.php b/api/components/OAuth2/Grants/ClientCredentialsGrant.php deleted file mode 100644 index fa72668..0000000 --- a/api/components/OAuth2/Grants/ClientCredentialsGrant.php +++ /dev/null @@ -1,12 +0,0 @@ -<?php -declare(strict_types=1); - -namespace api\components\OAuth2\Grants; - -use api\components\OAuth2\CryptTrait; -use League\OAuth2\Server\Grant\ClientCredentialsGrant as BaseClientCredentialsGrant; - -class ClientCredentialsGrant extends BaseClientCredentialsGrant { - use CryptTrait; - -} diff --git a/api/components/OAuth2/ResponseTypes/BearerTokenResponse.php b/api/components/OAuth2/ResponseTypes/BearerTokenResponse.php deleted file mode 100644 index 63e2c6e..0000000 --- a/api/components/OAuth2/ResponseTypes/BearerTokenResponse.php +++ /dev/null @@ -1,12 +0,0 @@ -<?php -declare(strict_types=1); - -namespace api\components\OAuth2\ResponseTypes; - -use api\components\OAuth2\CryptTrait; -use League\OAuth2\Server\ResponseTypes\BearerTokenResponse as BaseBearerTokenResponse; - -class BearerTokenResponse extends BaseBearerTokenResponse { - use CryptTrait; - -} diff --git a/api/components/Tokens/TokenReader.php b/api/components/Tokens/TokenReader.php index 282da4d..70b5bf5 100644 --- a/api/components/Tokens/TokenReader.php +++ b/api/components/Tokens/TokenReader.php @@ -30,6 +30,9 @@ final readonly class TokenReader { return $this->token->claims()->get('client_id', false) ?: null; } + /** + * @return list<string>|null + */ public function getScopes(): ?array { $scopes = $this->token->claims()->get('scope', false); if ($scopes !== false) { diff --git a/api/config/config.php b/api/config/config.php index ef44aff..e1dbe1c 100644 --- a/api/config/config.php +++ b/api/config/config.php @@ -26,9 +26,6 @@ return [ 'user' => [ 'class' => api\components\User\Component::class, ], - 'oauth' => [ - 'class' => api\components\OAuth2\Component::class, - ], 'tokens' => [ 'class' => api\components\Tokens\Component::class, 'privateKeyPath' => getenv('JWT_PRIVATE_KEY_PATH') ?: __DIR__ . '/../../data/certs/private.pem', diff --git a/api/modules/oauth/controllers/AuthorizationController.php b/api/modules/oauth/controllers/AuthorizationController.php index 351dcf4..03a51e6 100644 --- a/api/modules/oauth/controllers/AuthorizationController.php +++ b/api/modules/oauth/controllers/AuthorizationController.php @@ -9,10 +9,20 @@ use api\rbac\Permissions as P; use GuzzleHttp\Psr7\ServerRequest; use Psr\Http\Message\ServerRequestInterface; use Yii; +use yii\base\Module; use yii\filters\AccessControl; use yii\helpers\ArrayHelper; -class AuthorizationController extends Controller { +final class AuthorizationController extends Controller { + + public function __construct( + string $id, + Module $module, + private readonly OauthProcess $oauthProcess, + array $config = [], + ) { + parent::__construct($id, $module, $config); + } public function behaviors(): array { return ArrayHelper::merge(Controller::behaviors(), [ @@ -45,19 +55,15 @@ class AuthorizationController extends Controller { } public function actionValidate(): array { - return $this->createOauthProcess()->validate($this->getServerRequest()); + return $this->oauthProcess->validate($this->getServerRequest()); } public function actionComplete(): array { - return $this->createOauthProcess()->complete($this->getServerRequest()); + return $this->oauthProcess->complete($this->getServerRequest()); } public function actionToken(): array { - return $this->createOauthProcess()->getToken($this->getServerRequest()); - } - - private function createOauthProcess(): OauthProcess { - return new OauthProcess(Yii::$app->oauth->getAuthServer()); + return $this->oauthProcess->getToken($this->getServerRequest()); } private function getServerRequest(): ServerRequestInterface { diff --git a/api/modules/oauth/models/OauthProcess.php b/api/modules/oauth/models/OauthProcess.php index a5e320c..85ce25f 100644 --- a/api/modules/oauth/models/OauthProcess.php +++ b/api/modules/oauth/models/OauthProcess.php @@ -3,9 +3,9 @@ declare(strict_types=1); namespace api\modules\oauth\models; -use api\components\OAuth2\Entities\UserEntity; -use api\components\OAuth2\Events\RequestedRefreshToken; use api\rbac\Permissions as P; +use common\components\OAuth2\Entities\UserEntity; +use common\components\OAuth2\Events\RequestedRefreshToken; use common\models\Account; use common\models\OauthClient; use common\models\OauthSession; @@ -18,14 +18,16 @@ use Psr\Http\Message\ServerRequestInterface; use Webmozart\Assert\Assert; use Yii; -class OauthProcess { +final readonly class OauthProcess { private const array INTERNAL_PERMISSIONS_TO_PUBLIC_SCOPES = [ P::OBTAIN_OWN_ACCOUNT_INFO => 'account_info', P::OBTAIN_ACCOUNT_EMAIL => 'account_email', ]; - public function __construct(private readonly AuthorizationServer $server) { + public function __construct( + private AuthorizationServer $server, + ) { } /** @@ -43,8 +45,7 @@ class OauthProcess { * * In addition, you can pass the description value to override the application's description. * - * @param ServerRequestInterface $request - * @return array + * @return array<mixed> */ public function validate(ServerRequestInterface $request): array { try { @@ -77,8 +78,7 @@ class OauthProcess { * If the field is present, it will be interpreted as any value resulting in false positives. * Otherwise, the value will be interpreted as "true". * - * @param ServerRequestInterface $request - * @return array + * @return array<mixed> */ public function complete(ServerRequestInterface $request): array { try { @@ -144,8 +144,7 @@ class OauthProcess { * grant_type, * ] * - * @param ServerRequestInterface $request - * @return array + * @return array<mixed> */ public function getToken(ServerRequestInterface $request): array { $params = (array)$request->getParsedBody(); @@ -232,11 +231,9 @@ class OauthProcess { } /** - * @param ServerRequestInterface $request - * @param OauthClient $client * @param ScopeEntityInterface[] $scopes * - * @return array + * @return array<mixed> */ private function buildSuccessResponse(ServerRequestInterface $request, OauthClient $client, array $scopes): array { return [ @@ -262,7 +259,7 @@ class OauthProcess { /** * @param ScopeEntityInterface[] $scopes - * @return array + * @return string[] */ private function buildScopesArray(array $scopes): array { $result = []; @@ -273,6 +270,15 @@ class OauthProcess { return $result; } + /** + * @return array{ + * success: false, + * error: string, + * parameter: string|null, + * statusCode: int, + * redirectUri?: string, + * } + */ private function buildCompleteErrorResponse(OAuthServerException $e): array { $hint = $e->getPayload()['hint'] ?? ''; if (preg_match('/the `(\w+)` scope/', $hint, $matches)) { @@ -304,8 +310,10 @@ class OauthProcess { * * Part of the existing texts are the legacy from the previous implementation. * - * @param OAuthServerException $e - * @return array + * @return array{ + * error: string, + * message: string, + * } */ private function buildIssueErrorResponse(OAuthServerException $e): array { $errorType = $e->getErrorType(); @@ -331,6 +339,9 @@ class OauthProcess { return new OAuthServerException('Client must accept authentication request.', 0, 'accept_required', 401); } + /** + * @return list<string> + */ private function getScopesList(AuthorizationRequestInterface $request): array { return array_values(array_map(fn(ScopeEntityInterface $scope): string => $scope->getIdentifier(), $request->getScopes())); } diff --git a/api/tests/functional/_steps/OauthSteps.php b/api/tests/functional/_steps/OauthSteps.php index e35ab03..4a22a89 100644 --- a/api/tests/functional/_steps/OauthSteps.php +++ b/api/tests/functional/_steps/OauthSteps.php @@ -3,8 +3,8 @@ declare(strict_types=1); namespace api\tests\functional\_steps; -use api\components\OAuth2\Repositories\PublicScopeRepository; use api\tests\FunctionalTester; +use common\components\OAuth2\Repositories\PublicScopeRepository; class OauthSteps extends FunctionalTester { diff --git a/api/tests/unit/components/OAuth2/Entities/AccessTokenEntityTest.php b/api/tests/unit/components/OAuth2/Entities/AccessTokenEntityTest.php index b22115d..8bfcf2b 100644 --- a/api/tests/unit/components/OAuth2/Entities/AccessTokenEntityTest.php +++ b/api/tests/unit/components/OAuth2/Entities/AccessTokenEntityTest.php @@ -3,8 +3,8 @@ declare(strict_types=1); namespace api\tests\unit\components\OAuth2\Entities; -use api\components\OAuth2\Entities\AccessTokenEntity; use api\tests\unit\TestCase; +use common\components\OAuth2\Entities\AccessTokenEntity; use DateTimeImmutable; use League\OAuth2\Server\Entities\ClientEntityInterface; use League\OAuth2\Server\Entities\ScopeEntityInterface; diff --git a/autocompletion.php b/autocompletion.php index f930039..257612f 100644 --- a/autocompletion.php +++ b/autocompletion.php @@ -34,7 +34,6 @@ abstract class BaseApplication extends yii\base\Application { * * @property \api\components\User\Component $user * @property \api\components\ReCaptcha\Component $reCaptcha - * @property \api\components\OAuth2\Component $oauth * @property \api\components\Tokens\Component $tokens * @property \api\components\Tokens\TokensFactory $tokensFactory * diff --git a/api/components/OAuth2/Component.php b/common/components/OAuth2/AuthorizationServerFactory.php similarity index 82% rename from api/components/OAuth2/Component.php rename to common/components/OAuth2/AuthorizationServerFactory.php index cc0675a..fd2630e 100644 --- a/api/components/OAuth2/Component.php +++ b/common/components/OAuth2/AuthorizationServerFactory.php @@ -1,26 +1,16 @@ <?php declare(strict_types=1); -namespace api\components\OAuth2; +namespace common\components\OAuth2; use Carbon\CarbonInterval; use DateInterval; use League\OAuth2\Server\AuthorizationServer; use yii\base\Component as BaseComponent; -final class Component extends BaseComponent { +final class AuthorizationServerFactory extends BaseComponent { - private ?AuthorizationServer $_authServer = null; - - public function getAuthServer(): AuthorizationServer { - if ($this->_authServer === null) { - $this->_authServer = $this->createAuthServer(); - } - - return $this->_authServer; - } - - private function createAuthServer(): AuthorizationServer { + public static function build(): AuthorizationServer { $clientsRepo = new Repositories\ClientRepository(); $accessTokensRepo = new Repositories\AccessTokenRepository(); $publicScopesRepo = new Repositories\PublicScopeRepository(); diff --git a/api/components/OAuth2/CryptTrait.php b/common/components/OAuth2/CryptTrait.php similarity index 81% rename from api/components/OAuth2/CryptTrait.php rename to common/components/OAuth2/CryptTrait.php index 643578e..bcfa475 100644 --- a/api/components/OAuth2/CryptTrait.php +++ b/common/components/OAuth2/CryptTrait.php @@ -1,7 +1,7 @@ <?php declare(strict_types=1); -namespace api\components\OAuth2; +namespace common\components\OAuth2; use LogicException; use RangeException; @@ -18,11 +18,11 @@ use Yii; */ trait CryptTrait { - protected function encrypt($unencryptedData): string { + protected function encrypt(string $unencryptedData): string { return Yii::$app->tokens->encryptValue($unencryptedData); } - protected function decrypt($encryptedData): string { + protected function decrypt(string $encryptedData): string { try { return Yii::$app->tokens->decryptValue($encryptedData); } catch (SodiumException|RangeException $e) { diff --git a/api/components/OAuth2/Entities/AccessTokenEntity.php b/common/components/OAuth2/Entities/AccessTokenEntity.php similarity index 93% rename from api/components/OAuth2/Entities/AccessTokenEntity.php rename to common/components/OAuth2/Entities/AccessTokenEntity.php index 15243a2..ecd3854 100644 --- a/api/components/OAuth2/Entities/AccessTokenEntity.php +++ b/common/components/OAuth2/Entities/AccessTokenEntity.php @@ -1,7 +1,7 @@ <?php declare(strict_types=1); -namespace api\components\OAuth2\Entities; +namespace common\components\OAuth2\Entities; use League\OAuth2\Server\CryptKeyInterface; use League\OAuth2\Server\Entities\AccessTokenEntityInterface; diff --git a/api/components/OAuth2/Entities/AuthCodeEntity.php b/common/components/OAuth2/Entities/AuthCodeEntity.php similarity index 75% rename from api/components/OAuth2/Entities/AuthCodeEntity.php rename to common/components/OAuth2/Entities/AuthCodeEntity.php index 1db3362..bd68d1c 100644 --- a/api/components/OAuth2/Entities/AuthCodeEntity.php +++ b/common/components/OAuth2/Entities/AuthCodeEntity.php @@ -1,14 +1,14 @@ <?php declare(strict_types=1); -namespace api\components\OAuth2\Entities; +namespace common\components\OAuth2\Entities; use League\OAuth2\Server\Entities\AuthCodeEntityInterface; use League\OAuth2\Server\Entities\Traits\AuthCodeTrait; use League\OAuth2\Server\Entities\Traits\EntityTrait; use League\OAuth2\Server\Entities\Traits\TokenEntityTrait; -class AuthCodeEntity implements AuthCodeEntityInterface { +final class AuthCodeEntity implements AuthCodeEntityInterface { use EntityTrait; use AuthCodeTrait; use TokenEntityTrait; diff --git a/api/components/OAuth2/Entities/ClientEntity.php b/common/components/OAuth2/Entities/ClientEntity.php similarity index 77% rename from api/components/OAuth2/Entities/ClientEntity.php rename to common/components/OAuth2/Entities/ClientEntity.php index 4d375c3..5ea23ec 100644 --- a/api/components/OAuth2/Entities/ClientEntity.php +++ b/common/components/OAuth2/Entities/ClientEntity.php @@ -1,19 +1,19 @@ <?php declare(strict_types=1); -namespace api\components\OAuth2\Entities; +namespace common\components\OAuth2\Entities; use League\OAuth2\Server\Entities\ClientEntityInterface; use League\OAuth2\Server\Entities\Traits\ClientTrait; use League\OAuth2\Server\Entities\Traits\EntityTrait; -class ClientEntity implements ClientEntityInterface { +final class ClientEntity implements ClientEntityInterface { use EntityTrait; use ClientTrait; /** - * @param non-empty-string $id - * @param string|string[] $redirectUri + * @phpstan-param non-empty-string $id + * @phpstan-param string|list<string> $redirectUri */ public function __construct( string $id, diff --git a/api/components/OAuth2/Entities/ScopeEntity.php b/common/components/OAuth2/Entities/ScopeEntity.php similarity index 66% rename from api/components/OAuth2/Entities/ScopeEntity.php rename to common/components/OAuth2/Entities/ScopeEntity.php index 24895c2..6c3de48 100644 --- a/api/components/OAuth2/Entities/ScopeEntity.php +++ b/common/components/OAuth2/Entities/ScopeEntity.php @@ -1,16 +1,19 @@ <?php declare(strict_types=1); -namespace api\components\OAuth2\Entities; +namespace common\components\OAuth2\Entities; use League\OAuth2\Server\Entities\ScopeEntityInterface; use League\OAuth2\Server\Entities\Traits\EntityTrait; use League\OAuth2\Server\Entities\Traits\ScopeTrait; -class ScopeEntity implements ScopeEntityInterface { +final class ScopeEntity implements ScopeEntityInterface { use EntityTrait; use ScopeTrait; + /** + * @phpstan-param non-empty-string $id + */ public function __construct(string $id) { $this->identifier = $id; } diff --git a/api/components/OAuth2/Entities/UserEntity.php b/common/components/OAuth2/Entities/UserEntity.php similarity index 71% rename from api/components/OAuth2/Entities/UserEntity.php rename to common/components/OAuth2/Entities/UserEntity.php index 0328763..4c01aa5 100644 --- a/api/components/OAuth2/Entities/UserEntity.php +++ b/common/components/OAuth2/Entities/UserEntity.php @@ -1,12 +1,12 @@ <?php declare(strict_types=1); -namespace api\components\OAuth2\Entities; +namespace common\components\OAuth2\Entities; use League\OAuth2\Server\Entities\Traits\EntityTrait; use League\OAuth2\Server\Entities\UserEntityInterface; -class UserEntity implements UserEntityInterface { +final class UserEntity implements UserEntityInterface { use EntityTrait; public function __construct(int $id) { diff --git a/common/components/OAuth2/Events/RequestedRefreshToken.php b/common/components/OAuth2/Events/RequestedRefreshToken.php new file mode 100644 index 0000000..f312416 --- /dev/null +++ b/common/components/OAuth2/Events/RequestedRefreshToken.php @@ -0,0 +1,10 @@ +<?php +declare(strict_types=1); + +namespace common\components\OAuth2\Events; + +use League\OAuth2\Server\EventEmitting\AbstractEvent; + +final class RequestedRefreshToken extends AbstractEvent { + +} diff --git a/api/components/OAuth2/Grants/AuthCodeGrant.php b/common/components/OAuth2/Grants/AuthCodeGrant.php similarity index 69% rename from api/components/OAuth2/Grants/AuthCodeGrant.php rename to common/components/OAuth2/Grants/AuthCodeGrant.php index fa16d27..9dd7031 100644 --- a/api/components/OAuth2/Grants/AuthCodeGrant.php +++ b/common/components/OAuth2/Grants/AuthCodeGrant.php @@ -1,35 +1,23 @@ <?php declare(strict_types=1); -namespace api\components\OAuth2\Grants; +namespace common\components\OAuth2\Grants; -use api\components\OAuth2\CryptTrait; -use api\components\OAuth2\Events\RequestedRefreshToken; -use api\components\OAuth2\Repositories\PublicScopeRepository; +use common\components\OAuth2\CryptTrait; +use common\components\OAuth2\Events\RequestedRefreshToken; +use common\components\OAuth2\Repositories\PublicScopeRepository; use DateInterval; use League\OAuth2\Server\Entities\AccessTokenEntityInterface; use League\OAuth2\Server\Entities\ClientEntityInterface; -use League\OAuth2\Server\Entities\ScopeEntityInterface; use League\OAuth2\Server\Exception\OAuthServerException; -use League\OAuth2\Server\Exception\UniqueTokenIdentifierConstraintViolationException; use League\OAuth2\Server\Grant\AuthCodeGrant as BaseAuthCodeGrant; use League\OAuth2\Server\RequestEvent; use Psr\Http\Message\ServerRequestInterface; use yii\helpers\StringHelper; -class AuthCodeGrant extends BaseAuthCodeGrant { +final class AuthCodeGrant extends BaseAuthCodeGrant { use CryptTrait; - /** - * @param DateInterval $accessTokenTTL - * @param ClientEntityInterface $client - * @param string|null $userIdentifier - * @param ScopeEntityInterface[] $scopes - * - * @return AccessTokenEntityInterface - * @throws OAuthServerException - * @throws UniqueTokenIdentifierConstraintViolationException - */ protected function issueAccessToken( DateInterval $accessTokenTTL, ClientEntityInterface $client, diff --git a/common/components/OAuth2/Grants/ClientCredentialsGrant.php b/common/components/OAuth2/Grants/ClientCredentialsGrant.php new file mode 100644 index 0000000..4df9356 --- /dev/null +++ b/common/components/OAuth2/Grants/ClientCredentialsGrant.php @@ -0,0 +1,12 @@ +<?php +declare(strict_types=1); + +namespace common\components\OAuth2\Grants; + +use common\components\OAuth2\CryptTrait; +use League\OAuth2\Server\Grant\ClientCredentialsGrant as BaseClientCredentialsGrant; + +final class ClientCredentialsGrant extends BaseClientCredentialsGrant { + use CryptTrait; + +} diff --git a/api/components/OAuth2/Grants/RefreshTokenGrant.php b/common/components/OAuth2/Grants/RefreshTokenGrant.php similarity index 85% rename from api/components/OAuth2/Grants/RefreshTokenGrant.php rename to common/components/OAuth2/Grants/RefreshTokenGrant.php index 1ea1a9c..6b5d3d4 100644 --- a/api/components/OAuth2/Grants/RefreshTokenGrant.php +++ b/common/components/OAuth2/Grants/RefreshTokenGrant.php @@ -1,11 +1,11 @@ <?php declare(strict_types=1); -namespace api\components\OAuth2\Grants; +namespace common\components\OAuth2\Grants; -use api\components\OAuth2\CryptTrait; use api\components\Tokens\TokenReader; use Carbon\FactoryImmutable; +use common\components\OAuth2\CryptTrait; use common\models\OauthSession; use InvalidArgumentException; use Lcobucci\JWT\Validation\Constraint\LooseValidAt; @@ -18,7 +18,7 @@ use Psr\Http\Message\ServerRequestInterface; use Throwable; use Yii; -class RefreshTokenGrant extends BaseRefreshTokenGrant { +final class RefreshTokenGrant extends BaseRefreshTokenGrant { use CryptTrait; /** @@ -26,11 +26,7 @@ class RefreshTokenGrant extends BaseRefreshTokenGrant { * If received refresh token is matches the legacy token template, * restore the information from the legacy storage. * - * @param ServerRequestInterface $request - * @param string $clientId - * - * @return array - * @throws OAuthServerException + * @inheritDoc */ protected function validateOldRefreshToken(ServerRequestInterface $request, string $clientId): array { $refreshToken = $this->getRequestParameter('refresh_token', $request); @@ -45,18 +41,13 @@ class RefreshTokenGrant extends BaseRefreshTokenGrant { * Currently we're not rotating refresh tokens. * So we're overriding this method to always return null, which means, * that refresh_token will not be issued. - * - * @param AccessTokenEntityInterface $accessToken - * - * @return RefreshTokenEntityInterface|null */ protected function issueRefreshToken(AccessTokenEntityInterface $accessToken): ?RefreshTokenEntityInterface { return null; } /** - * @param string $refreshToken - * @return array + * @return array<string, mixed> * @throws OAuthServerException */ private function validateLegacyRefreshToken(string $refreshToken): array { @@ -91,14 +82,7 @@ class RefreshTokenGrant extends BaseRefreshTokenGrant { } /** - * @return array{ - * client_id: string, - * refresh_token_id?: string, - * access_token_id?: string, - * scopes: list<string>|null, - * user_id: string|null, - * expire_time: int|null, - * } + * @return array<string, mixed> * @throws OAuthServerException */ private function validateAccessToken(string $jwt): array { diff --git a/api/components/OAuth2/Keys/EmptyKey.php b/common/components/OAuth2/Keys/EmptyKey.php similarity index 76% rename from api/components/OAuth2/Keys/EmptyKey.php rename to common/components/OAuth2/Keys/EmptyKey.php index 216cc4c..82f241b 100644 --- a/api/components/OAuth2/Keys/EmptyKey.php +++ b/common/components/OAuth2/Keys/EmptyKey.php @@ -1,11 +1,11 @@ <?php declare(strict_types=1); -namespace api\components\OAuth2\Keys; +namespace common\components\OAuth2\Keys; use League\OAuth2\Server\CryptKeyInterface; -class EmptyKey implements CryptKeyInterface { +final class EmptyKey implements CryptKeyInterface { public function getKeyPath(): string { return ''; diff --git a/api/components/OAuth2/Repositories/AccessTokenRepository.php b/common/components/OAuth2/Repositories/AccessTokenRepository.php similarity index 63% rename from api/components/OAuth2/Repositories/AccessTokenRepository.php rename to common/components/OAuth2/Repositories/AccessTokenRepository.php index affaf2f..6bad3db 100644 --- a/api/components/OAuth2/Repositories/AccessTokenRepository.php +++ b/common/components/OAuth2/Repositories/AccessTokenRepository.php @@ -1,28 +1,23 @@ <?php declare(strict_types=1); -namespace api\components\OAuth2\Repositories; +namespace common\components\OAuth2\Repositories; -use api\components\OAuth2\Entities\AccessTokenEntity; +use common\components\OAuth2\Entities\AccessTokenEntity; use League\OAuth2\Server\Entities\AccessTokenEntityInterface; use League\OAuth2\Server\Entities\ClientEntityInterface; use League\OAuth2\Server\Repositories\AccessTokenRepositoryInterface; -class AccessTokenRepository implements AccessTokenRepositoryInterface { +final class AccessTokenRepository implements AccessTokenRepositoryInterface { /** - * Create a new access token - * - * @param ClientEntityInterface $clientEntity - * @param \League\OAuth2\Server\Entities\ScopeEntityInterface[] $scopes - * @param mixed $userIdentifier - * - * @return AccessTokenEntityInterface + * @inheritDoc + * @phpstan-param non-empty-string|null $userIdentifier */ public function getNewToken( ClientEntityInterface $clientEntity, array $scopes, - $userIdentifier = null, + ?string $userIdentifier = null, ): AccessTokenEntityInterface { $accessToken = new AccessTokenEntity(); $accessToken->setClient($clientEntity); @@ -38,11 +33,11 @@ class AccessTokenRepository implements AccessTokenRepositoryInterface { // We don't store access tokens, so there's no need to do anything here } - public function revokeAccessToken($tokenId): void { + public function revokeAccessToken(string $tokenId): void { // We don't store access tokens, so there's no need to do anything here } - public function isAccessTokenRevoked($tokenId): bool { + public function isAccessTokenRevoked(string $tokenId): bool { return false; } diff --git a/api/components/OAuth2/Repositories/AuthCodeRepository.php b/common/components/OAuth2/Repositories/AuthCodeRepository.php similarity index 57% rename from api/components/OAuth2/Repositories/AuthCodeRepository.php rename to common/components/OAuth2/Repositories/AuthCodeRepository.php index 4a71f9e..324c5d6 100644 --- a/api/components/OAuth2/Repositories/AuthCodeRepository.php +++ b/common/components/OAuth2/Repositories/AuthCodeRepository.php @@ -1,13 +1,13 @@ <?php declare(strict_types=1); -namespace api\components\OAuth2\Repositories; +namespace common\components\OAuth2\Repositories; -use api\components\OAuth2\Entities\AuthCodeEntity; +use common\components\OAuth2\Entities\AuthCodeEntity; use League\OAuth2\Server\Entities\AuthCodeEntityInterface; use League\OAuth2\Server\Repositories\AuthCodeRepositoryInterface; -class AuthCodeRepository implements AuthCodeRepositoryInterface { +final class AuthCodeRepository implements AuthCodeRepositoryInterface { public function getNewAuthCode(): AuthCodeEntityInterface { return new AuthCodeEntity(); @@ -16,10 +16,10 @@ class AuthCodeRepository implements AuthCodeRepositoryInterface { public function persistNewAuthCode(AuthCodeEntityInterface $authCodeEntity): void { } - public function revokeAuthCode($codeId): void { + public function revokeAuthCode(string $codeId): void { } - public function isAuthCodeRevoked($codeId): bool { + public function isAuthCodeRevoked(string $codeId): bool { return false; } diff --git a/api/components/OAuth2/Repositories/ClientRepository.php b/common/components/OAuth2/Repositories/ClientRepository.php similarity index 61% rename from api/components/OAuth2/Repositories/ClientRepository.php rename to common/components/OAuth2/Repositories/ClientRepository.php index 0503aa1..859fcfa 100644 --- a/api/components/OAuth2/Repositories/ClientRepository.php +++ b/common/components/OAuth2/Repositories/ClientRepository.php @@ -1,26 +1,27 @@ <?php declare(strict_types=1); -namespace api\components\OAuth2\Repositories; +namespace common\components\OAuth2\Repositories; -use api\components\OAuth2\Entities\ClientEntity; +use common\components\OAuth2\Entities\ClientEntity; use common\models\OauthClient; use League\OAuth2\Server\Entities\ClientEntityInterface; use League\OAuth2\Server\Repositories\ClientRepositoryInterface; -class ClientRepository implements ClientRepositoryInterface { +final class ClientRepository implements ClientRepositoryInterface { - public function getClientEntity($clientId): ?ClientEntityInterface { - $client = $this->findModel($clientId); + public function getClientEntity(string $clientIdentifier): ?ClientEntityInterface { + $client = $this->findModel($clientIdentifier); if ($client === null) { return null; } - return new ClientEntity($client->id, $client->name, $client->redirect_uri ?? '', (bool)$client->is_trusted); + // @phpstan-ignore argument.type + return new ClientEntity($client->id, $client->name, $client->redirect_uri ?: '', (bool)$client->is_trusted); } - public function validateClient($clientId, $clientSecret, $grantType): bool { - $client = $this->findModel($clientId); + public function validateClient(string $clientIdentifier, ?string $clientSecret, ?string $grantType): bool { + $client = $this->findModel($clientIdentifier); if ($client === null) { return false; } diff --git a/api/components/OAuth2/Repositories/EmptyScopeRepository.php b/common/components/OAuth2/Repositories/EmptyScopeRepository.php similarity index 80% rename from api/components/OAuth2/Repositories/EmptyScopeRepository.php rename to common/components/OAuth2/Repositories/EmptyScopeRepository.php index 33dc7f5..85e148b 100644 --- a/api/components/OAuth2/Repositories/EmptyScopeRepository.php +++ b/common/components/OAuth2/Repositories/EmptyScopeRepository.php @@ -1,7 +1,7 @@ <?php declare(strict_types=1); -namespace api\components\OAuth2\Repositories; +namespace common\components\OAuth2\Repositories; use League\OAuth2\Server\Entities\ClientEntityInterface; use League\OAuth2\Server\Entities\ScopeEntityInterface; @@ -12,7 +12,7 @@ use League\OAuth2\Server\Repositories\ScopeRepositoryInterface; * To create an instance of the authorization server, you need to pass the scopes * repository. This class acts as a dummy to meet this requirement. */ -class EmptyScopeRepository implements ScopeRepositoryInterface { +final class EmptyScopeRepository implements ScopeRepositoryInterface { public function getScopeEntityByIdentifier($identifier): ?ScopeEntityInterface { return null; @@ -20,9 +20,9 @@ class EmptyScopeRepository implements ScopeRepositoryInterface { public function finalizeScopes( array $scopes, - $grantType, + string $grantType, ClientEntityInterface $clientEntity, - $userIdentifier = null, + ?string $userIdentifier = null, ?string $authCodeId = null, ): array { return $scopes; diff --git a/api/components/OAuth2/Repositories/InternalScopeRepository.php b/common/components/OAuth2/Repositories/InternalScopeRepository.php similarity index 85% rename from api/components/OAuth2/Repositories/InternalScopeRepository.php rename to common/components/OAuth2/Repositories/InternalScopeRepository.php index dcd2027..cd36ee0 100644 --- a/api/components/OAuth2/Repositories/InternalScopeRepository.php +++ b/common/components/OAuth2/Repositories/InternalScopeRepository.php @@ -1,17 +1,17 @@ <?php declare(strict_types=1); -namespace api\components\OAuth2\Repositories; +namespace common\components\OAuth2\Repositories; -use api\components\OAuth2\Entities\ClientEntity; -use api\components\OAuth2\Entities\ScopeEntity; use api\rbac\Permissions as P; +use common\components\OAuth2\Entities\ClientEntity; +use common\components\OAuth2\Entities\ScopeEntity; use League\OAuth2\Server\Entities\ClientEntityInterface; use League\OAuth2\Server\Entities\ScopeEntityInterface; use League\OAuth2\Server\Exception\OAuthServerException; use League\OAuth2\Server\Repositories\ScopeRepositoryInterface; -class InternalScopeRepository implements ScopeRepositoryInterface { +final class InternalScopeRepository implements ScopeRepositoryInterface { private const array ALLOWED_SCOPES = [ P::CHANGE_ACCOUNT_USERNAME, @@ -39,9 +39,9 @@ class InternalScopeRepository implements ScopeRepositoryInterface { */ public function finalizeScopes( array $scopes, - $grantType, + string $grantType, ClientEntityInterface $clientEntity, - $userIdentifier = null, + ?string $userIdentifier = null, ?string $authCodeId = null, ): array { if (empty($scopes)) { diff --git a/api/components/OAuth2/Repositories/PublicScopeRepository.php b/common/components/OAuth2/Repositories/PublicScopeRepository.php similarity index 86% rename from api/components/OAuth2/Repositories/PublicScopeRepository.php rename to common/components/OAuth2/Repositories/PublicScopeRepository.php index 3ebd19f..961e738 100644 --- a/api/components/OAuth2/Repositories/PublicScopeRepository.php +++ b/common/components/OAuth2/Repositories/PublicScopeRepository.php @@ -1,15 +1,15 @@ <?php declare(strict_types=1); -namespace api\components\OAuth2\Repositories; +namespace common\components\OAuth2\Repositories; -use api\components\OAuth2\Entities\ScopeEntity; use api\rbac\Permissions as P; +use common\components\OAuth2\Entities\ScopeEntity; use League\OAuth2\Server\Entities\ClientEntityInterface; use League\OAuth2\Server\Entities\ScopeEntityInterface; use League\OAuth2\Server\Repositories\ScopeRepositoryInterface; -class PublicScopeRepository implements ScopeRepositoryInterface { +final class PublicScopeRepository implements ScopeRepositoryInterface { public const string OFFLINE_ACCESS = 'offline_access'; public const string CHANGE_SKIN = 'change_skin'; @@ -41,9 +41,9 @@ class PublicScopeRepository implements ScopeRepositoryInterface { public function finalizeScopes( array $scopes, - $grantType, + string $grantType, ClientEntityInterface $clientEntity, - $userIdentifier = null, + ?string $userIdentifier = null, ?string $authCodeId = null, ): array { return $scopes; diff --git a/api/components/OAuth2/Repositories/RefreshTokenRepository.php b/common/components/OAuth2/Repositories/RefreshTokenRepository.php similarity index 63% rename from api/components/OAuth2/Repositories/RefreshTokenRepository.php rename to common/components/OAuth2/Repositories/RefreshTokenRepository.php index 199e342..4c5febe 100644 --- a/api/components/OAuth2/Repositories/RefreshTokenRepository.php +++ b/common/components/OAuth2/Repositories/RefreshTokenRepository.php @@ -1,12 +1,12 @@ <?php declare(strict_types=1); -namespace api\components\OAuth2\Repositories; +namespace common\components\OAuth2\Repositories; use League\OAuth2\Server\Entities\RefreshTokenEntityInterface; use League\OAuth2\Server\Repositories\RefreshTokenRepositoryInterface; -class RefreshTokenRepository implements RefreshTokenRepositoryInterface { +final class RefreshTokenRepository implements RefreshTokenRepositoryInterface { public function getNewRefreshToken(): ?RefreshTokenEntityInterface { return null; @@ -16,11 +16,11 @@ class RefreshTokenRepository implements RefreshTokenRepositoryInterface { // Do nothing } - public function revokeRefreshToken($tokenId): void { + public function revokeRefreshToken(string $tokenId): void { // Do nothing } - public function isRefreshTokenRevoked($tokenId): bool { + public function isRefreshTokenRevoked(string $tokenId): bool { return false; } diff --git a/common/components/OAuth2/ResponseTypes/BearerTokenResponse.php b/common/components/OAuth2/ResponseTypes/BearerTokenResponse.php new file mode 100644 index 0000000..ad6508b --- /dev/null +++ b/common/components/OAuth2/ResponseTypes/BearerTokenResponse.php @@ -0,0 +1,12 @@ +<?php +declare(strict_types=1); + +namespace common\components\OAuth2\ResponseTypes; + +use common\components\OAuth2\CryptTrait; +use League\OAuth2\Server\ResponseTypes\BearerTokenResponse as BaseBearerTokenResponse; + +final class BearerTokenResponse extends BaseBearerTokenResponse { + use CryptTrait; + +} diff --git a/common/config/config.php b/common/config/config.php index e7b8e2c..f1653d6 100644 --- a/common/config/config.php +++ b/common/config/config.php @@ -26,6 +26,7 @@ return [ 'http://' . (getenv('CHRLY_HOST') ?: 'skinsystem.ely.by'), ], ], + League\OAuth2\Server\AuthorizationServer::class => common\components\OAuth2\AuthorizationServerFactory::build(...), ], ], 'components' => [ diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 4876fb8..fa9d25c 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -5,151 +5,6 @@ parameters: count: 1 path: api/components/ErrorHandler.php - - - message: "#^Property api\\\\components\\\\OAuth2\\\\Entities\\\\ScopeEntity\\:\\:\\$identifier \\(non\\-empty\\-string\\) does not accept string\\.$#" - count: 1 - path: api/components/OAuth2/Entities/ScopeEntity.php - - - - message: "#^Method api\\\\components\\\\OAuth2\\\\Grants\\\\AuthCodeGrant\\:\\:decrypt\\(\\) has parameter \\$encryptedData with no type specified\\.$#" - count: 1 - path: api/components/OAuth2/Grants/AuthCodeGrant.php - - - - message: "#^Method api\\\\components\\\\OAuth2\\\\Grants\\\\AuthCodeGrant\\:\\:encrypt\\(\\) has parameter \\$unencryptedData with no type specified\\.$#" - count: 1 - path: api/components/OAuth2/Grants/AuthCodeGrant.php - - - - message: "#^Method api\\\\components\\\\OAuth2\\\\Grants\\\\ClientCredentialsGrant\\:\\:decrypt\\(\\) has parameter \\$encryptedData with no type specified\\.$#" - count: 1 - path: api/components/OAuth2/Grants/ClientCredentialsGrant.php - - - - message: "#^Method api\\\\components\\\\OAuth2\\\\Grants\\\\ClientCredentialsGrant\\:\\:encrypt\\(\\) has parameter \\$unencryptedData with no type specified\\.$#" - count: 1 - path: api/components/OAuth2/Grants/ClientCredentialsGrant.php - - - - message: "#^Method api\\\\components\\\\OAuth2\\\\Grants\\\\RefreshTokenGrant\\:\\:decrypt\\(\\) has parameter \\$encryptedData with no type specified\\.$#" - count: 1 - path: api/components/OAuth2/Grants/RefreshTokenGrant.php - - - - message: "#^Method api\\\\components\\\\OAuth2\\\\Grants\\\\RefreshTokenGrant\\:\\:encrypt\\(\\) has parameter \\$unencryptedData with no type specified\\.$#" - count: 1 - path: api/components/OAuth2/Grants/RefreshTokenGrant.php - - - - message: "#^Method api\\\\components\\\\OAuth2\\\\Grants\\\\RefreshTokenGrant\\:\\:validateAccessToken\\(\\) should return array\\{client_id\\: string, refresh_token_id\\?\\: string, access_token_id\\?\\: string, scopes\\: array\\<int, string\\>\\|null, user_id\\: string\\|null, expire_time\\: int\\|null\\} but returns array\\{client_id\\: string\\|null, refresh_token_id\\: '', access_token_id\\: '', scopes\\: array\\|null, user_id\\: int\\|null, expire_time\\: null\\}\\.$#" - count: 1 - path: api/components/OAuth2/Grants/RefreshTokenGrant.php - - - - message: "#^Method api\\\\components\\\\OAuth2\\\\Grants\\\\RefreshTokenGrant\\:\\:validateLegacyRefreshToken\\(\\) return type has no value type specified in iterable type array\\.$#" - count: 1 - path: api/components/OAuth2/Grants/RefreshTokenGrant.php - - - - message: "#^Method api\\\\components\\\\OAuth2\\\\Grants\\\\RefreshTokenGrant\\:\\:validateOldRefreshToken\\(\\) return type has no value type specified in iterable type array\\.$#" - count: 1 - path: api/components/OAuth2/Grants/RefreshTokenGrant.php - - - - message: "#^Method api\\\\components\\\\OAuth2\\\\Repositories\\\\AccessTokenRepository\\:\\:isAccessTokenRevoked\\(\\) has parameter \\$tokenId with no type specified\\.$#" - count: 1 - path: api/components/OAuth2/Repositories/AccessTokenRepository.php - - - - message: "#^Method api\\\\components\\\\OAuth2\\\\Repositories\\\\AccessTokenRepository\\:\\:revokeAccessToken\\(\\) has parameter \\$tokenId with no type specified\\.$#" - count: 1 - path: api/components/OAuth2/Repositories/AccessTokenRepository.php - - - - message: "#^Method api\\\\components\\\\OAuth2\\\\Repositories\\\\AuthCodeRepository\\:\\:isAuthCodeRevoked\\(\\) has parameter \\$codeId with no type specified\\.$#" - count: 1 - path: api/components/OAuth2/Repositories/AuthCodeRepository.php - - - - message: "#^Method api\\\\components\\\\OAuth2\\\\Repositories\\\\AuthCodeRepository\\:\\:revokeAuthCode\\(\\) has parameter \\$codeId with no type specified\\.$#" - count: 1 - path: api/components/OAuth2/Repositories/AuthCodeRepository.php - - - - message: "#^Method api\\\\components\\\\OAuth2\\\\Repositories\\\\ClientRepository\\:\\:getClientEntity\\(\\) has parameter \\$clientId with no type specified\\.$#" - count: 1 - path: api/components/OAuth2/Repositories/ClientRepository.php - - - - message: "#^Method api\\\\components\\\\OAuth2\\\\Repositories\\\\ClientRepository\\:\\:validateClient\\(\\) has parameter \\$clientId with no type specified\\.$#" - count: 1 - path: api/components/OAuth2/Repositories/ClientRepository.php - - - - message: "#^Method api\\\\components\\\\OAuth2\\\\Repositories\\\\ClientRepository\\:\\:validateClient\\(\\) has parameter \\$clientSecret with no type specified\\.$#" - count: 1 - path: api/components/OAuth2/Repositories/ClientRepository.php - - - - message: "#^Method api\\\\components\\\\OAuth2\\\\Repositories\\\\ClientRepository\\:\\:validateClient\\(\\) has parameter \\$grantType with no type specified\\.$#" - count: 1 - path: api/components/OAuth2/Repositories/ClientRepository.php - - - - message: "#^Parameter \\#1 \\$id of class api\\\\components\\\\OAuth2\\\\Entities\\\\ClientEntity constructor expects non\\-empty\\-string, string given\\.$#" - count: 1 - path: api/components/OAuth2/Repositories/ClientRepository.php - - - - message: "#^Method api\\\\components\\\\OAuth2\\\\Repositories\\\\EmptyScopeRepository\\:\\:finalizeScopes\\(\\) has parameter \\$grantType with no type specified\\.$#" - count: 1 - path: api/components/OAuth2/Repositories/EmptyScopeRepository.php - - - - message: "#^Method api\\\\components\\\\OAuth2\\\\Repositories\\\\EmptyScopeRepository\\:\\:finalizeScopes\\(\\) has parameter \\$userIdentifier with no type specified\\.$#" - count: 1 - path: api/components/OAuth2/Repositories/EmptyScopeRepository.php - - - - message: "#^Method api\\\\components\\\\OAuth2\\\\Repositories\\\\InternalScopeRepository\\:\\:finalizeScopes\\(\\) has parameter \\$grantType with no type specified\\.$#" - count: 1 - path: api/components/OAuth2/Repositories/InternalScopeRepository.php - - - - message: "#^Method api\\\\components\\\\OAuth2\\\\Repositories\\\\InternalScopeRepository\\:\\:finalizeScopes\\(\\) has parameter \\$userIdentifier with no type specified\\.$#" - count: 1 - path: api/components/OAuth2/Repositories/InternalScopeRepository.php - - - - message: "#^Method api\\\\components\\\\OAuth2\\\\Repositories\\\\PublicScopeRepository\\:\\:finalizeScopes\\(\\) has parameter \\$grantType with no type specified\\.$#" - count: 1 - path: api/components/OAuth2/Repositories/PublicScopeRepository.php - - - - message: "#^Method api\\\\components\\\\OAuth2\\\\Repositories\\\\PublicScopeRepository\\:\\:finalizeScopes\\(\\) has parameter \\$userIdentifier with no type specified\\.$#" - count: 1 - path: api/components/OAuth2/Repositories/PublicScopeRepository.php - - - - message: "#^Method api\\\\components\\\\OAuth2\\\\Repositories\\\\RefreshTokenRepository\\:\\:isRefreshTokenRevoked\\(\\) has parameter \\$tokenId with no type specified\\.$#" - count: 1 - path: api/components/OAuth2/Repositories/RefreshTokenRepository.php - - - - message: "#^Method api\\\\components\\\\OAuth2\\\\Repositories\\\\RefreshTokenRepository\\:\\:revokeRefreshToken\\(\\) has parameter \\$tokenId with no type specified\\.$#" - count: 1 - path: api/components/OAuth2/Repositories/RefreshTokenRepository.php - - - - message: "#^Method api\\\\components\\\\OAuth2\\\\ResponseTypes\\\\BearerTokenResponse\\:\\:decrypt\\(\\) has parameter \\$encryptedData with no type specified\\.$#" - count: 1 - path: api/components/OAuth2/ResponseTypes/BearerTokenResponse.php - - - - message: "#^Method api\\\\components\\\\OAuth2\\\\ResponseTypes\\\\BearerTokenResponse\\:\\:encrypt\\(\\) has parameter \\$unencryptedData with no type specified\\.$#" - count: 1 - path: api/components/OAuth2/ResponseTypes/BearerTokenResponse.php - - message: "#^Property api\\\\components\\\\ReCaptcha\\\\Component\\:\\:\\$public has no type specified\\.$#" count: 1 @@ -220,11 +75,6 @@ parameters: count: 1 path: api/components/Tokens/Component.php - - - message: "#^Method api\\\\components\\\\Tokens\\\\TokenReader\\:\\:getScopes\\(\\) return type has no value type specified in iterable type array\\.$#" - count: 1 - path: api/components/Tokens/TokenReader.php - - message: "#^Property api\\\\components\\\\User\\\\Component\\:\\:\\$loginUrl type has no value type specified in iterable type array\\.$#" count: 1 @@ -305,16 +155,6 @@ parameters: count: 1 path: api/models/authentication/ConfirmEmailForm.php - - - message: "#^Property api\\\\models\\\\authentication\\\\ForgotPasswordForm\\:\\:\\$captcha has no type specified\\.$#" - count: 1 - path: api/models/authentication/ForgotPasswordForm.php - - - - message: "#^Property api\\\\models\\\\authentication\\\\ForgotPasswordForm\\:\\:\\$login has no type specified\\.$#" - count: 1 - path: api/models/authentication/ForgotPasswordForm.php - - message: "#^Property api\\\\models\\\\authentication\\\\RecoverPasswordForm\\:\\:\\$key has no type specified\\.$#" count: 1 @@ -695,46 +535,6 @@ parameters: count: 1 path: api/modules/oauth/models/OauthClientTypeForm.php - - - message: "#^Method api\\\\modules\\\\oauth\\\\models\\\\OauthProcess\\:\\:buildCompleteErrorResponse\\(\\) return type has no value type specified in iterable type array\\.$#" - count: 1 - path: api/modules/oauth/models/OauthProcess.php - - - - message: "#^Method api\\\\modules\\\\oauth\\\\models\\\\OauthProcess\\:\\:buildIssueErrorResponse\\(\\) return type has no value type specified in iterable type array\\.$#" - count: 1 - path: api/modules/oauth/models/OauthProcess.php - - - - message: "#^Method api\\\\modules\\\\oauth\\\\models\\\\OauthProcess\\:\\:buildScopesArray\\(\\) return type has no value type specified in iterable type array\\.$#" - count: 1 - path: api/modules/oauth/models/OauthProcess.php - - - - message: "#^Method api\\\\modules\\\\oauth\\\\models\\\\OauthProcess\\:\\:buildSuccessResponse\\(\\) return type has no value type specified in iterable type array\\.$#" - count: 1 - path: api/modules/oauth/models/OauthProcess.php - - - - message: "#^Method api\\\\modules\\\\oauth\\\\models\\\\OauthProcess\\:\\:complete\\(\\) return type has no value type specified in iterable type array\\.$#" - count: 1 - path: api/modules/oauth/models/OauthProcess.php - - - - message: "#^Method api\\\\modules\\\\oauth\\\\models\\\\OauthProcess\\:\\:getScopesList\\(\\) return type has no value type specified in iterable type array\\.$#" - count: 1 - path: api/modules/oauth/models/OauthProcess.php - - - - message: "#^Method api\\\\modules\\\\oauth\\\\models\\\\OauthProcess\\:\\:getToken\\(\\) return type has no value type specified in iterable type array\\.$#" - count: 1 - path: api/modules/oauth/models/OauthProcess.php - - - - message: "#^Method api\\\\modules\\\\oauth\\\\models\\\\OauthProcess\\:\\:validate\\(\\) return type has no value type specified in iterable type array\\.$#" - count: 1 - path: api/modules/oauth/models/OauthProcess.php - - message: "#^Method api\\\\modules\\\\session\\\\Module\\:\\:error\\(\\) has parameter \\$message with no type specified\\.$#" count: 1