_JEXEC & copyright

This commit is contained in:
Artem Vasilev 2024-03-09 19:03:09 +03:00
parent f53892aac5
commit 366ddf3534
5 changed files with 136 additions and 55 deletions

View File

@ -1,4 +1,11 @@
<?php <?php
/**
* @package Joomla.Site
* @subpackage com_oauthserver
*
* @copyright (c) 2024. Webmasterskaya. <https://webmasterskaya.xyz>
* @license MIT; see LICENSE.txt
**/
namespace Webmasterskaya\Component\OauthServer\Site\Repository; namespace Webmasterskaya\Component\OauthServer\Site\Repository;
@ -10,21 +17,23 @@ use Webmasterskaya\Component\OauthServer\Administrator\Model\AccessTokenModel;
use Webmasterskaya\Component\OauthServer\Administrator\Model\ClientModel; use Webmasterskaya\Component\OauthServer\Administrator\Model\ClientModel;
use Webmasterskaya\Component\OauthServer\Site\Entity\AccessToken; use Webmasterskaya\Component\OauthServer\Site\Entity\AccessToken;
\defined('_JEXEC') or die;
class AccessTokenRepository implements AccessTokenRepositoryInterface class AccessTokenRepository implements AccessTokenRepositoryInterface
{ {
private AccessTokenModel $accessTokenModel; private AccessTokenModel $accessTokenModel;
private ClientModel $clientModel; private ClientModel $clientModel;
/** /**
* @param \Webmasterskaya\Component\OauthServer\Administrator\Model\AccessTokenModel $accessTokenModel * @param \Webmasterskaya\Component\OauthServer\Administrator\Model\AccessTokenModel $accessTokenModel
* @param \Webmasterskaya\Component\OauthServer\Administrator\Model\ClientModel $clientModel * @param \Webmasterskaya\Component\OauthServer\Administrator\Model\ClientModel $clientModel
* *
* @since version * @since version
*/ */
public function __construct(AccessTokenModel $accessTokenModel, ClientModel $clientModel) public function __construct(AccessTokenModel $accessTokenModel, ClientModel $clientModel)
{ {
$this->accessTokenModel = $accessTokenModel; $this->accessTokenModel = $accessTokenModel;
$this->clientModel = $clientModel; $this->clientModel = $clientModel;
} }
public function getNewToken(ClientEntityInterface $clientEntity, array $scopes, $userIdentifier = null): AccessTokenEntityInterface public function getNewToken(ClientEntityInterface $clientEntity, array $scopes, $userIdentifier = null): AccessTokenEntityInterface
@ -33,7 +42,8 @@ class AccessTokenRepository implements AccessTokenRepositoryInterface
$accessToken->setClient($clientEntity); $accessToken->setClient($clientEntity);
$accessToken->setUserIdentifier($userIdentifier); $accessToken->setUserIdentifier($userIdentifier);
foreach ($scopes as $scope) { foreach ($scopes as $scope)
{
$accessToken->addScope($scope); $accessToken->addScope($scope);
} }
@ -43,16 +53,21 @@ class AccessTokenRepository implements AccessTokenRepositoryInterface
public function persistNewAccessToken(AccessTokenEntityInterface $accessTokenEntity): void public function persistNewAccessToken(AccessTokenEntityInterface $accessTokenEntity): void
{ {
$found = false; $found = false;
try { try
{
/** @var AccessToken $accessTokenEntity */ /** @var AccessToken $accessTokenEntity */
$accessToken = $this->accessTokenModel->getItemByIdentifier($accessTokenEntity->getIdentifier()); $accessToken = $this->accessTokenModel->getItemByIdentifier($accessTokenEntity->getIdentifier());
if ($accessToken->id > 0) { if ($accessToken->id > 0)
{
$found = true; $found = true;
} }
} catch (\Throwable $e) { }
catch (\Throwable $e)
{
} }
if ($found) { if ($found)
{
throw UniqueTokenIdentifierConstraintViolationException::create(); throw UniqueTokenIdentifierConstraintViolationException::create();
} }
@ -76,7 +91,8 @@ class AccessTokenRepository implements AccessTokenRepositoryInterface
{ {
$accessToken = $this->accessTokenModel->getItemByIdentifier($tokenId); $accessToken = $this->accessTokenModel->getItemByIdentifier($tokenId);
if (!$accessToken->id) { if (!$accessToken->id)
{
return true; return true;
} }

View File

@ -1,15 +1,23 @@
<?php <?php
/**
* @package Joomla.Site
* @subpackage com_oauthserver
*
* @copyright (c) 2024. Webmasterskaya. <https://webmasterskaya.xyz>
* @license MIT; see LICENSE.txt
**/
namespace Webmasterskaya\Component\OauthServer\Site\Repository; namespace Webmasterskaya\Component\OauthServer\Site\Repository;
use League\OAuth2\Server\Entities\AuthCodeEntityInterface; use League\OAuth2\Server\Entities\AuthCodeEntityInterface;
use League\OAuth2\Server\Exception\UniqueTokenIdentifierConstraintViolationException; use League\OAuth2\Server\Exception\UniqueTokenIdentifierConstraintViolationException;
use League\OAuth2\Server\Repositories\AuthCodeRepositoryInterface; use League\OAuth2\Server\Repositories\AuthCodeRepositoryInterface;
use Wamania\Snowball\NotFoundException;
use Webmasterskaya\Component\OauthServer\Administrator\Model\AuthCodeModel; use Webmasterskaya\Component\OauthServer\Administrator\Model\AuthCodeModel;
use Webmasterskaya\Component\OauthServer\Administrator\Model\ClientModel; use Webmasterskaya\Component\OauthServer\Administrator\Model\ClientModel;
use Webmasterskaya\Component\OauthServer\Site\Entity\AuthCode; use Webmasterskaya\Component\OauthServer\Site\Entity\AuthCode;
\defined('_JEXEC') or die;
class AuthCodeRepository implements AuthCodeRepositoryInterface class AuthCodeRepository implements AuthCodeRepositoryInterface
{ {
private AuthCodeModel $authCodeModel; private AuthCodeModel $authCodeModel;
@ -17,14 +25,15 @@ class AuthCodeRepository implements AuthCodeRepositoryInterface
private ClientModel $clientModel; private ClientModel $clientModel;
/** /**
* @param \Webmasterskaya\Component\OauthServer\Administrator\Model\AuthCodeModel $authCodeModel * @param \Webmasterskaya\Component\OauthServer\Administrator\Model\AuthCodeModel $authCodeModel
* @param \Webmasterskaya\Component\OauthServer\Administrator\Model\ClientModel $clientModel * @param \Webmasterskaya\Component\OauthServer\Administrator\Model\ClientModel $clientModel
*
* @since version * @since version
*/ */
public function __construct(AuthCodeModel $authCodeModel, ClientModel $clientModel) public function __construct(AuthCodeModel $authCodeModel, ClientModel $clientModel)
{ {
$this->authCodeModel = $authCodeModel; $this->authCodeModel = $authCodeModel;
$this->clientModel = $clientModel; $this->clientModel = $clientModel;
} }
public function getNewAuthCode(): AuthCode public function getNewAuthCode(): AuthCode
@ -35,17 +44,22 @@ class AuthCodeRepository implements AuthCodeRepositoryInterface
public function persistNewAuthCode(AuthCodeEntityInterface $authCodeEntity) public function persistNewAuthCode(AuthCodeEntityInterface $authCodeEntity)
{ {
$found = false; $found = false;
try { try
{
$authCode = $this->authCodeModel->getItemByIdentifier($authCodeEntity->getIdentifier()); $authCode = $this->authCodeModel->getItemByIdentifier($authCodeEntity->getIdentifier());
if ($authCode->id > 0) { if ($authCode->id > 0)
{
$found = true; $found = true;
} }
} catch (\Throwable $e) { }
catch (\Throwable $e)
{
} }
if ($found) { if ($found)
{
throw UniqueTokenIdentifierConstraintViolationException::create(); throw UniqueTokenIdentifierConstraintViolationException::create();
} }
@ -68,7 +82,8 @@ class AuthCodeRepository implements AuthCodeRepositoryInterface
{ {
$authCode = $this->authCodeModel->getItemByIdentifier($codeId); $authCode = $this->authCodeModel->getItemByIdentifier($codeId);
if (empty($authCode->id)) { if (empty($authCode->id))
{
return true; return true;
} }

View File

@ -1,4 +1,11 @@
<?php <?php
/**
* @package Joomla.Site
* @subpackage com_oauthserver
*
* @copyright (c) 2024. Webmasterskaya. <https://webmasterskaya.xyz>
* @license MIT; see LICENSE.txt
**/
namespace Webmasterskaya\Component\OauthServer\Site\Repository; namespace Webmasterskaya\Component\OauthServer\Site\Repository;
@ -9,6 +16,8 @@ use League\OAuth2\Server\Repositories\ClientRepositoryInterface;
use Webmasterskaya\Component\OauthServer\Administrator\Model\ClientModel; use Webmasterskaya\Component\OauthServer\Administrator\Model\ClientModel;
use Webmasterskaya\Component\OauthServer\Site\Entity\Client; use Webmasterskaya\Component\OauthServer\Site\Entity\Client;
\defined('_JEXEC') or die;
class ClientRepository implements ClientRepositoryInterface class ClientRepository implements ClientRepositoryInterface
{ {
private ClientModel $clientModel; private ClientModel $clientModel;
@ -20,6 +29,7 @@ class ClientRepository implements ClientRepositoryInterface
/** /**
* @param $clientIdentifier * @param $clientIdentifier
*
* @return \League\OAuth2\Server\Entities\ClientEntityInterface|null * @return \League\OAuth2\Server\Entities\ClientEntityInterface|null
* @throws \Exception * @throws \Exception
* @since version * @since version
@ -28,7 +38,8 @@ class ClientRepository implements ClientRepositoryInterface
{ {
$item = $this->clientModel->getItemByIdentifier($clientIdentifier); $item = $this->clientModel->getItemByIdentifier($clientIdentifier);
if (empty($item->id)) { if (empty($item->id))
{
return null; return null;
} }
@ -39,19 +50,23 @@ class ClientRepository implements ClientRepositoryInterface
{ {
$item = $this->clientModel->getItemByIdentifier($clientIdentifier); $item = $this->clientModel->getItemByIdentifier($clientIdentifier);
if (empty($item->id)) { if (empty($item->id))
{
return false; return false;
} }
if (!$item->active) { if (!$item->active)
{
return false; return false;
} }
if (!$this->isGrantSupported($item, $grantType)) { if (!$this->isGrantSupported($item, $grantType))
{
return false; return false;
} }
if (!!$item->public || hash_equals((string)$item->secret, (string)$clientSecret)) { if (!!$item->public || hash_equals((string) $item->secret, (string) $clientSecret))
{
return true; return true;
} }
@ -63,22 +78,24 @@ class ClientRepository implements ClientRepositoryInterface
$clientEntity = new Client(); $clientEntity = new Client();
$clientEntity->setName($client->name); $clientEntity->setName($client->name);
$clientEntity->setIdentifier($client->identifier); $clientEntity->setIdentifier($client->identifier);
$clientEntity->setRedirectUri(ArrayHelper::getColumn((array)$client->redirect_uris, 'uri')); $clientEntity->setRedirectUri(ArrayHelper::getColumn((array) $client->redirect_uris, 'uri'));
$clientEntity->setConfidential(!$client->public); $clientEntity->setConfidential(!$client->public);
$clientEntity->setAllowPlainTextPkce((bool)$client->allow_plain_text_pkce); $clientEntity->setAllowPlainTextPkce((bool) $client->allow_plain_text_pkce);
return $clientEntity; return $clientEntity;
} }
private function isGrantSupported(\stdClass|CMSObject $client, ?string $grant): bool private function isGrantSupported(\stdClass|CMSObject $client, ?string $grant): bool
{ {
if (null === $grant) { if (null === $grant)
{
return true; return true;
} }
$grants = array_map('strval', (array)$client->grants); $grants = array_map('strval', (array) $client->grants);
if (empty($grants)) { if (empty($grants))
{
return true; return true;
} }

View File

@ -1,4 +1,11 @@
<?php <?php
/**
* @package Joomla.Site
* @subpackage com_oauthserver
*
* @copyright (c) 2024. Webmasterskaya. <https://webmasterskaya.xyz>
* @license MIT; see LICENSE.txt
**/
namespace Webmasterskaya\Component\OauthServer\Site\Repository; namespace Webmasterskaya\Component\OauthServer\Site\Repository;
@ -9,6 +16,8 @@ use Webmasterskaya\Component\OauthServer\Administrator\Model\AccessTokenModel;
use Webmasterskaya\Component\OauthServer\Administrator\Model\RefreshTokenModel; use Webmasterskaya\Component\OauthServer\Administrator\Model\RefreshTokenModel;
use Webmasterskaya\Component\OauthServer\Site\Entity\RefreshToken; use Webmasterskaya\Component\OauthServer\Site\Entity\RefreshToken;
\defined('_JEXEC') or die;
class RefreshTokenRepository implements RefreshTokenRepositoryInterface class RefreshTokenRepository implements RefreshTokenRepositoryInterface
{ {
@ -17,14 +26,15 @@ class RefreshTokenRepository implements RefreshTokenRepositoryInterface
private AccessTokenModel $accessTokenModel; private AccessTokenModel $accessTokenModel;
/** /**
* @param \Webmasterskaya\Component\OauthServer\Administrator\Model\RefreshTokenModel $refreshTokenModel * @param \Webmasterskaya\Component\OauthServer\Administrator\Model\RefreshTokenModel $refreshTokenModel
* @param \Webmasterskaya\Component\OauthServer\Administrator\Model\AccessTokenModel $accessTokenModel * @param \Webmasterskaya\Component\OauthServer\Administrator\Model\AccessTokenModel $accessTokenModel
*
* @since version * @since version
*/ */
public function __construct(RefreshTokenModel $refreshTokenModel, AccessTokenModel $accessTokenModel) public function __construct(RefreshTokenModel $refreshTokenModel, AccessTokenModel $accessTokenModel)
{ {
$this->refreshTokenModel = $refreshTokenModel; $this->refreshTokenModel = $refreshTokenModel;
$this->accessTokenModel = $accessTokenModel; $this->accessTokenModel = $accessTokenModel;
} }
@ -36,16 +46,21 @@ class RefreshTokenRepository implements RefreshTokenRepositoryInterface
public function persistNewRefreshToken(RefreshTokenEntityInterface $refreshTokenEntity) public function persistNewRefreshToken(RefreshTokenEntityInterface $refreshTokenEntity)
{ {
$found = false; $found = false;
try { try
{
$refreshToken = $this->refreshTokenModel->getItemByIdentifier($refreshTokenEntity->getIdentifier()); $refreshToken = $this->refreshTokenModel->getItemByIdentifier($refreshTokenEntity->getIdentifier());
if ($refreshToken->id > 0) { if ($refreshToken->id > 0)
{
$found = true; $found = true;
} }
} catch (\Exception $e) { }
catch (\Exception $e)
{
} }
if ($found) { if ($found)
{
throw UniqueTokenIdentifierConstraintViolationException::create(); throw UniqueTokenIdentifierConstraintViolationException::create();
} }
@ -68,7 +83,8 @@ class RefreshTokenRepository implements RefreshTokenRepositoryInterface
{ {
$refreshToken = $this->refreshTokenModel->getItemByIdentifier($tokenId); $refreshToken = $this->refreshTokenModel->getItemByIdentifier($tokenId);
if (empty($refreshToken->id)) { if (empty($refreshToken->id))
{
return true; return true;
} }

View File

@ -1,4 +1,11 @@
<?php <?php
/**
* @package Joomla.Site
* @subpackage com_oauthserver
*
* @copyright (c) 2024. Webmasterskaya. <https://webmasterskaya.xyz>
* @license MIT; see LICENSE.txt
**/
namespace Webmasterskaya\Component\OauthServer\Site\Repository; namespace Webmasterskaya\Component\OauthServer\Site\Repository;
@ -12,6 +19,8 @@ use Webmasterskaya\Component\OauthServer\Administrator\Event\Scope\ScopeResolveE
use Webmasterskaya\Component\OauthServer\Administrator\Model\ClientModel; use Webmasterskaya\Component\OauthServer\Administrator\Model\ClientModel;
use Webmasterskaya\Component\OauthServer\Site\Entity\Scope; use Webmasterskaya\Component\OauthServer\Site\Entity\Scope;
\defined('_JEXEC') or die;
class ScopeRepository implements ScopeRepositoryInterface, DispatcherAwareInterface class ScopeRepository implements ScopeRepositoryInterface, DispatcherAwareInterface
{ {
use DispatcherAwareTrait; use DispatcherAwareTrait;
@ -27,7 +36,8 @@ class ScopeRepository implements ScopeRepositoryInterface, DispatcherAwareInterf
{ {
$defined = ['userinfo', 'email']; $defined = ['userinfo', 'email'];
if (!in_array($identifier, $defined)) { if (!in_array($identifier, $defined))
{
return null; return null;
} }
@ -38,10 +48,11 @@ class ScopeRepository implements ScopeRepositoryInterface, DispatcherAwareInterf
} }
/** /**
* @param Scope[] $scopes * @param Scope[] $scopes
* @param $grantType * @param $grantType
* @param \League\OAuth2\Server\Entities\ClientEntityInterface $clientEntity * @param \League\OAuth2\Server\Entities\ClientEntityInterface $clientEntity
* @param null $userIdentifier * @param null $userIdentifier
*
* @return mixed * @return mixed
* @throws \League\OAuth2\Server\Exception\OAuthServerException * @throws \League\OAuth2\Server\Exception\OAuthServerException
* @since version * @since version
@ -67,8 +78,9 @@ class ScopeRepository implements ScopeRepositoryInterface, DispatcherAwareInterf
} }
/** /**
* @param object $client * @param object $client
* @param array $requestedScopes * @param array $requestedScopes
*
* @return array * @return array
* @throws \League\OAuth2\Server\Exception\OAuthServerException * @throws \League\OAuth2\Server\Exception\OAuthServerException
* @since version * @since version
@ -77,26 +89,31 @@ class ScopeRepository implements ScopeRepositoryInterface, DispatcherAwareInterf
{ {
$clientScopes = $client->scopes; $clientScopes = $client->scopes;
if (empty($clientScopes)) { if (empty($clientScopes))
{
return $requestedScopes; return $requestedScopes;
} }
$clientScopes = array_map(function ($item) { $clientScopes = array_map(function ($item) {
$scope = new Scope(); $scope = new Scope();
$scope->setIdentifier((string)$item); $scope->setIdentifier((string) $item);
return $scope; return $scope;
}, $clientScopes); }, $clientScopes);
if (empty($requestedScopes)) { if (empty($requestedScopes))
{
return $clientScopes; return $clientScopes;
} }
$finalizedScopes = []; $finalizedScopes = [];
$clientScopesAsStrings = array_map('strval', $clientScopes); $clientScopesAsStrings = array_map('strval', $clientScopes);
foreach ($requestedScopes as $requestedScope) { foreach ($requestedScopes as $requestedScope)
$requestedScopeAsString = (string)$requestedScope; {
if (!\in_array($requestedScopeAsString, $clientScopesAsStrings, true)) { $requestedScopeAsString = (string) $requestedScope;
if (!\in_array($requestedScopeAsString, $clientScopesAsStrings, true))
{
throw OAuthServerException::invalidScope($requestedScopeAsString); throw OAuthServerException::invalidScope($requestedScopeAsString);
} }