mirror of
https://github.com/Karaka-Management/phpOMS.git
synced 2026-02-11 06:28:40 +00:00
continue oauth client impl.
This commit is contained in:
parent
d2ccc2d15e
commit
793e7a5f15
|
|
@ -1,27 +0,0 @@
|
||||||
<?php
|
|
||||||
/**
|
|
||||||
* Orange Management
|
|
||||||
*
|
|
||||||
* PHP Version 7.4
|
|
||||||
*
|
|
||||||
* @package phpOMS\Auth\OAuth2
|
|
||||||
* @copyright Dennis Eichhorn
|
|
||||||
* @license OMS License 1.0
|
|
||||||
* @version 1.0.0
|
|
||||||
* @link https://orange-management.org
|
|
||||||
*/
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace phpOMS\Auth\OAuth2;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Client class.
|
|
||||||
*
|
|
||||||
* @package phpOMS\Auth\OAuth2
|
|
||||||
* @license OMS License 1.0
|
|
||||||
* @link https://orange-management.org
|
|
||||||
* @since 1.0.0
|
|
||||||
*/
|
|
||||||
final class Client
|
|
||||||
{
|
|
||||||
}
|
|
||||||
37
Auth/OAuth2/Grant/AuthorizationCode.php
Normal file
37
Auth/OAuth2/Grant/AuthorizationCode.php
Normal file
|
|
@ -0,0 +1,37 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Orange Management
|
||||||
|
*
|
||||||
|
* PHP Version 7.4
|
||||||
|
*
|
||||||
|
* @package phpOMS\Auth\OAuth2\Grant
|
||||||
|
* @copyright Dennis Eichhorn
|
||||||
|
* @license OMS License 1.0
|
||||||
|
* @version 1.0.0
|
||||||
|
* @link https://orange-management.org
|
||||||
|
* @see https://tools.ietf.org/html/rfc6749
|
||||||
|
*/
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace phpOMS\Auth\OAuth2\Grant;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provider class.
|
||||||
|
*
|
||||||
|
* @package phpOMS\Auth\OAuth2\Grant
|
||||||
|
* @license OMS License 1.0
|
||||||
|
* @link https://orange-management.org
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
class AuthorizationCode extends GrantAbstract
|
||||||
|
{
|
||||||
|
protected function getName() : string
|
||||||
|
{
|
||||||
|
return 'authorization_code';
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getRequiredRequestParameters() : array
|
||||||
|
{
|
||||||
|
return ['code'];
|
||||||
|
}
|
||||||
|
}
|
||||||
37
Auth/OAuth2/Grant/ClientCredentials.php
Normal file
37
Auth/OAuth2/Grant/ClientCredentials.php
Normal file
|
|
@ -0,0 +1,37 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Orange Management
|
||||||
|
*
|
||||||
|
* PHP Version 7.4
|
||||||
|
*
|
||||||
|
* @package phpOMS\Auth\OAuth2\Grant
|
||||||
|
* @copyright Dennis Eichhorn
|
||||||
|
* @license OMS License 1.0
|
||||||
|
* @version 1.0.0
|
||||||
|
* @link https://orange-management.org
|
||||||
|
* @see https://tools.ietf.org/html/rfc6749
|
||||||
|
*/
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace phpOMS\Auth\OAuth2\Grant;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provider class.
|
||||||
|
*
|
||||||
|
* @package phpOMS\Auth\OAuth2\Grant
|
||||||
|
* @license OMS License 1.0
|
||||||
|
* @link https://orange-management.org
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
class ClientCredentials extends GrantAbstract
|
||||||
|
{
|
||||||
|
protected function getName() : string
|
||||||
|
{
|
||||||
|
return 'client_credentials';
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getRequiredRequestParameters() : array
|
||||||
|
{
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
52
Auth/OAuth2/Grant/GrantAbstract.php
Normal file
52
Auth/OAuth2/Grant/GrantAbstract.php
Normal file
|
|
@ -0,0 +1,52 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Orange Management
|
||||||
|
*
|
||||||
|
* PHP Version 7.4
|
||||||
|
*
|
||||||
|
* @package phpOMS\Auth\OAuth2\Grant
|
||||||
|
* @copyright Dennis Eichhorn
|
||||||
|
* @license OMS License 1.0
|
||||||
|
* @version 1.0.0
|
||||||
|
* @link https://orange-management.org
|
||||||
|
* @see https://tools.ietf.org/html/rfc6749
|
||||||
|
*/
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace phpOMS\Auth\OAuth2\Grant;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provider class.
|
||||||
|
*
|
||||||
|
* @package phpOMS\Auth\OAuth2\Grant
|
||||||
|
* @license OMS License 1.0
|
||||||
|
* @link https://orange-management.org
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
abstract class GrantAbstract
|
||||||
|
{
|
||||||
|
abstract protected function getName() : string;
|
||||||
|
|
||||||
|
abstract protected function getRequiredRequestParameters() : array;
|
||||||
|
|
||||||
|
public function __toString()
|
||||||
|
{
|
||||||
|
return $this->getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function prepareRequestParamters(array $defaults, array $options) : array
|
||||||
|
{
|
||||||
|
$defaullts['grant_type'] = $this->getName();
|
||||||
|
|
||||||
|
$required = $this->getRequiredRequestParameters();
|
||||||
|
$provided = \array_merge($defaults, $options);
|
||||||
|
|
||||||
|
foreach ($required as $name) {
|
||||||
|
if (!isset($provided[$name])) {
|
||||||
|
throw new \Exception();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $provided;
|
||||||
|
}
|
||||||
|
}
|
||||||
55
Auth/OAuth2/Grant/GrantFactory.php
Normal file
55
Auth/OAuth2/Grant/GrantFactory.php
Normal file
|
|
@ -0,0 +1,55 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Orange Management
|
||||||
|
*
|
||||||
|
* PHP Version 7.4
|
||||||
|
*
|
||||||
|
* @package phpOMS\Auth\OAuth2\Grant
|
||||||
|
* @copyright Dennis Eichhorn
|
||||||
|
* @license OMS License 1.0
|
||||||
|
* @version 1.0.0
|
||||||
|
* @link https://orange-management.org
|
||||||
|
* @see https://tools.ietf.org/html/rfc6749
|
||||||
|
*/
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace phpOMS\Auth\OAuth2\Grant;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provider class.
|
||||||
|
*
|
||||||
|
* @package phpOMS\Auth\OAuth2\Grant
|
||||||
|
* @license OMS License 1.0
|
||||||
|
* @link https://orange-management.org
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
class GrantFactory
|
||||||
|
{
|
||||||
|
protected array $registry = [];
|
||||||
|
|
||||||
|
public function setGrant(string $name, GrantAbstract $grant) : self
|
||||||
|
{
|
||||||
|
$this->registry[$name] = $grant;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getGrant(string $name) : AbstractGrant
|
||||||
|
{
|
||||||
|
if (!isset($this->registry[$name])) {
|
||||||
|
$this->registerDefaultGrant($name);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->registry[$name];
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function registerDefaultGrant(string $name) : self
|
||||||
|
{
|
||||||
|
$class = \str_replace(' ', '', \ucwords(\str_replace(['-', '_', ' ', $name])));
|
||||||
|
$class = 'phpOMS\\OAuth2\\Grant\\' . $class;
|
||||||
|
|
||||||
|
$this->checkGrant($class);
|
||||||
|
|
||||||
|
return $this->setGrant($name, new $class());
|
||||||
|
}
|
||||||
|
}
|
||||||
40
Auth/OAuth2/Grant/Password.php
Normal file
40
Auth/OAuth2/Grant/Password.php
Normal file
|
|
@ -0,0 +1,40 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Orange Management
|
||||||
|
*
|
||||||
|
* PHP Version 7.4
|
||||||
|
*
|
||||||
|
* @package phpOMS\Auth\OAuth2\Grant
|
||||||
|
* @copyright Dennis Eichhorn
|
||||||
|
* @license OMS License 1.0
|
||||||
|
* @version 1.0.0
|
||||||
|
* @link https://orange-management.org
|
||||||
|
* @see https://tools.ietf.org/html/rfc6749
|
||||||
|
*/
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace phpOMS\Auth\OAuth2\Grant;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provider class.
|
||||||
|
*
|
||||||
|
* @package phpOMS\Auth\OAuth2\Grant
|
||||||
|
* @license OMS License 1.0
|
||||||
|
* @link https://orange-management.org
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
class Password extends GrantAbstract
|
||||||
|
{
|
||||||
|
protected function getName() : string
|
||||||
|
{
|
||||||
|
return 'password';
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getRequiredRequestParameters() : array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'username',
|
||||||
|
'password',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
37
Auth/OAuth2/Grant/RefreshToken.php
Normal file
37
Auth/OAuth2/Grant/RefreshToken.php
Normal file
|
|
@ -0,0 +1,37 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Orange Management
|
||||||
|
*
|
||||||
|
* PHP Version 7.4
|
||||||
|
*
|
||||||
|
* @package phpOMS\Auth\OAuth2\Grant
|
||||||
|
* @copyright Dennis Eichhorn
|
||||||
|
* @license OMS License 1.0
|
||||||
|
* @version 1.0.0
|
||||||
|
* @link https://orange-management.org
|
||||||
|
* @see https://tools.ietf.org/html/rfc6749
|
||||||
|
*/
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace phpOMS\Auth\OAuth2\Grant;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provider class.
|
||||||
|
*
|
||||||
|
* @package phpOMS\Auth\OAuth2\Grant
|
||||||
|
* @license OMS License 1.0
|
||||||
|
* @link https://orange-management.org
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
class RefreshToken extends GrantAbstract
|
||||||
|
{
|
||||||
|
protected function getName() : string
|
||||||
|
{
|
||||||
|
return 'refresh_token';
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getRequiredRequestParameters() : array
|
||||||
|
{
|
||||||
|
return ['refresh_token'];
|
||||||
|
}
|
||||||
|
}
|
||||||
38
Auth/OAuth2/OptionProvider/HttpBasicAuthOptionProvider.php
Normal file
38
Auth/OAuth2/OptionProvider/HttpBasicAuthOptionProvider.php
Normal file
|
|
@ -0,0 +1,38 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Orange Management
|
||||||
|
*
|
||||||
|
* PHP Version 7.4
|
||||||
|
*
|
||||||
|
* @package phpOMS\Auth\OAuth2\OptionProvider
|
||||||
|
* @copyright Dennis Eichhorn
|
||||||
|
* @license OMS License 1.0
|
||||||
|
* @version 1.0.0
|
||||||
|
* @link https://orange-management.org
|
||||||
|
* @see https://tools.ietf.org/html/rfc6749
|
||||||
|
*/
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace phpOMS\Auth\OAuth2\OptionProvider;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provider class.
|
||||||
|
*
|
||||||
|
* @package phpOMS\Auth\OAuth2\OptionProvider
|
||||||
|
* @license OMS License 1.0
|
||||||
|
* @link https://orange-management.org
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
class HttpBasicAuthOptionProvider extends PostAuthOptionProvider
|
||||||
|
{
|
||||||
|
public function getAccessTokenOptions(string $method, array $params) : array
|
||||||
|
{
|
||||||
|
$encoded = \base64_encode($params['client_id'] . ':' . $params['client_secret']);
|
||||||
|
unset($params['client_id'], $params['client_secret']);
|
||||||
|
|
||||||
|
$options = parent::getAccessTokenOptions($method, $params);
|
||||||
|
$options['headers']['Authorization'] = 'Basic ' . $encoded;
|
||||||
|
|
||||||
|
return $options;
|
||||||
|
}
|
||||||
|
}
|
||||||
29
Auth/OAuth2/OptionProvider/OptionProviderInterface.php
Normal file
29
Auth/OAuth2/OptionProvider/OptionProviderInterface.php
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Orange Management
|
||||||
|
*
|
||||||
|
* PHP Version 7.4
|
||||||
|
*
|
||||||
|
* @package phpOMS\Auth\OAuth2\OptionProvider
|
||||||
|
* @copyright Dennis Eichhorn
|
||||||
|
* @license OMS License 1.0
|
||||||
|
* @version 1.0.0
|
||||||
|
* @link https://orange-management.org
|
||||||
|
* @see https://tools.ietf.org/html/rfc6749
|
||||||
|
*/
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace phpOMS\Auth\OAuth2\OptionProvider;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provider class.
|
||||||
|
*
|
||||||
|
* @package phpOMS\Auth\OAuth2\OptionProvider
|
||||||
|
* @license OMS License 1.0
|
||||||
|
* @link https://orange-management.org
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
interface OptionProviderInterface
|
||||||
|
{
|
||||||
|
public function getAccessTokenOptions(string $method, array $params) : array;
|
||||||
|
}
|
||||||
48
Auth/OAuth2/OptionProvider/PostAuthOptionProvider.php
Normal file
48
Auth/OAuth2/OptionProvider/PostAuthOptionProvider.php
Normal file
|
|
@ -0,0 +1,48 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Orange Management
|
||||||
|
*
|
||||||
|
* PHP Version 7.4
|
||||||
|
*
|
||||||
|
* @package phpOMS\Auth\OAuth2\OptionProvider
|
||||||
|
* @copyright Dennis Eichhorn
|
||||||
|
* @license OMS License 1.0
|
||||||
|
* @version 1.0.0
|
||||||
|
* @link https://orange-management.org
|
||||||
|
* @see https://tools.ietf.org/html/rfc6749
|
||||||
|
*/
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace phpOMS\Auth\OAuth2\OptionProvider;
|
||||||
|
|
||||||
|
use phpOMS\System\MimeType;
|
||||||
|
use phpOMS\Message\Http\RequestMethod;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provider class.
|
||||||
|
*
|
||||||
|
* @package phpOMS\Auth\OAuth2\OptionProvider
|
||||||
|
* @license OMS License 1.0
|
||||||
|
* @link https://orange-management.org
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
class PostAuthOptionProvider implements OptionProviderInterface
|
||||||
|
{
|
||||||
|
public function getAccessTokenOptions(string $method, array $params) : array
|
||||||
|
{
|
||||||
|
$options = [
|
||||||
|
'headers' => ['content-type' => MimeType::M_POST]
|
||||||
|
];
|
||||||
|
|
||||||
|
if ($method === RequestMethod::POST) {
|
||||||
|
$options['body'] = $this->getAccessTokenBody($params);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $options;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getAccessTokenBody(array $params) : string
|
||||||
|
{
|
||||||
|
return \http_build_query($params, null, '&', \PHP_QUERY_RFC3986);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -25,26 +25,49 @@ use phpOMS\Auth\OAuth2\AccessToken;
|
||||||
* @link https://orange-management.org
|
* @link https://orange-management.org
|
||||||
* @since 1.0.0
|
* @since 1.0.0
|
||||||
*/
|
*/
|
||||||
final class GeneralProvider
|
class GeneralProvider extends ProviderAbstract
|
||||||
{
|
{
|
||||||
/**
|
|
||||||
* Authorization url
|
|
||||||
*
|
|
||||||
* @var string
|
|
||||||
* @since 1.0.0
|
|
||||||
*/
|
|
||||||
private string $urlAuthorize;
|
private string $urlAuthorize;
|
||||||
|
|
||||||
/**
|
|
||||||
* Access token url
|
|
||||||
*
|
|
||||||
* @var string
|
|
||||||
* @since 1.0.0
|
|
||||||
*/
|
|
||||||
private string $urlAccessToken;
|
private string $urlAccessToken;
|
||||||
|
|
||||||
|
private string $urlResourceOwnerDetails;
|
||||||
|
|
||||||
|
private string $accessTokenMethod;
|
||||||
|
|
||||||
|
private string $accessTokenResourceOwnerId;
|
||||||
|
|
||||||
|
private ?array $scopes = null;
|
||||||
|
|
||||||
|
private string $scopeSeparator;
|
||||||
|
|
||||||
|
private string $responseCode;
|
||||||
|
|
||||||
|
private string $responseResourceOwnerId = 'id';
|
||||||
|
|
||||||
public function __construct(array $options = [], array $collaborators = [])
|
public function __construct(array $options = [], array $collaborators = [])
|
||||||
{
|
{
|
||||||
|
if (!isset($options['urlAuthorize'], $options['urlAccessToken'], $options['urlResourceOwnerDetails'])) {
|
||||||
|
throw new \InvalidArgumentException();
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($options as $key => $option) {
|
||||||
|
if (\property_exists($this, $key)) {
|
||||||
|
$this->{$key} = $option;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
parent::__construct([], $collaborators);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getBaseAuthorizationUrl() : string
|
||||||
|
{
|
||||||
|
return $this->urlAuthorize;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getBaseAccessTokenUrl(array $params = []) : string
|
||||||
|
{
|
||||||
|
return $this->urlAccessToken;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getDefaultScopes() : array
|
public function getDefaultScopes() : array
|
||||||
|
|
@ -67,7 +90,7 @@ final class GeneralProvider
|
||||||
return $this->scopeSeparator ?: parent::getScopeSeparator();
|
return $this->scopeSeparator ?: parent::getScopeSeparator();
|
||||||
}
|
}
|
||||||
|
|
||||||
private function createResourceOwner(array $reesponse, AccessToken $token) : GeneralResourceOwner
|
private function createResourceOwner(array $response, AccessToken $token) : GeneralResourceOwner
|
||||||
{
|
{
|
||||||
return new GeneralResourceOwner($response, $this->responseResourceOwnerId);
|
return new GeneralResourceOwner($response, $this->responseResourceOwnerId);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
0
Auth/OAuth2/Provider/GeneralResourceOwner.php
Normal file
0
Auth/OAuth2/Provider/GeneralResourceOwner.php
Normal file
|
|
@ -15,6 +15,11 @@ declare(strict_types=1);
|
||||||
|
|
||||||
namespace phpOMS\Auth\OAuth2\Provider;
|
namespace phpOMS\Auth\OAuth2\Provider;
|
||||||
|
|
||||||
|
use phpOMS\Message\Http\HttpResponse;
|
||||||
|
use phpOMS\Message\Http\RequestMethod;
|
||||||
|
use phpOMS\Uri\UriFactory;
|
||||||
|
use phpOMS\Utils\ArrayUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provider class.
|
* Provider class.
|
||||||
*
|
*
|
||||||
|
|
@ -25,7 +30,291 @@ namespace phpOMS\Auth\OAuth2\Provider;
|
||||||
*/
|
*/
|
||||||
abstract class ProviderAbstract
|
abstract class ProviderAbstract
|
||||||
{
|
{
|
||||||
|
protected const ACCESS_TOKEN_RESOURCE_OWNER_ID = null;
|
||||||
|
|
||||||
|
protected string $clientId;
|
||||||
|
|
||||||
|
protected string $clientSecret;
|
||||||
|
|
||||||
|
protected string $redirectUri;
|
||||||
|
|
||||||
|
protected string $state;
|
||||||
|
|
||||||
|
protected GrantFactory $grantFactory;
|
||||||
|
|
||||||
|
protected ReuqestFactory $requestFactory;
|
||||||
|
|
||||||
|
protected OptionProviderInterface $optionProvider;
|
||||||
|
|
||||||
public function __construct(array $options = [], array $collaborators = [])
|
public function __construct(array $options = [], array $collaborators = [])
|
||||||
{
|
{
|
||||||
|
foreach ($options as $key => $option) {
|
||||||
|
if (\property_exists($this, $key)) {
|
||||||
|
$this->{$key} = $option;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->setGrantFactory($collaborators['grantFactory'] ?? new GrantFactory());
|
||||||
|
$this->setRequestFactory($collaborators['requestFactory'] ?? new RequestFactory());
|
||||||
|
$this->setOptionProvider($collaborators['optionProvider'] ?? new PostAuthOptionProvider());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setGrantFactory(GrantFactory $factory) : self
|
||||||
|
{
|
||||||
|
$this->grantFactory = $factory;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getGrantFactory() : GrantFactory
|
||||||
|
{
|
||||||
|
return $this->grantFactory;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setRequestFactory(RequestFactory $factory) : self
|
||||||
|
{
|
||||||
|
$this->requestFactory = $factory;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getRequestFactory() : RequestFactory
|
||||||
|
{
|
||||||
|
return $this->requestFactory;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setOptionProvider(OptionProviderInterface $provider) : self
|
||||||
|
{
|
||||||
|
$this->optionProvider = $provider;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getOptionProvider() : OptionProviderInterface
|
||||||
|
{
|
||||||
|
return $this->optionProvider;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getState() : string
|
||||||
|
{
|
||||||
|
return $this->state;
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract public function getBaseAuthorizationUrl() : string;
|
||||||
|
|
||||||
|
abstract public function getBaseAccessTokenUrl(array $params = []) : string;
|
||||||
|
|
||||||
|
abstract public function getResourceOwnerDetailsUrl(AccessToken $token) : string;
|
||||||
|
|
||||||
|
protected function getRandomState(int $length = 32) : string
|
||||||
|
{
|
||||||
|
return \bin2hex(\random_bytes($length / 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract protected function getDefaultScopes() : array;
|
||||||
|
|
||||||
|
protected function getScopeSeparator() : string
|
||||||
|
{
|
||||||
|
return ',';
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getAuthorizationParameters(array $options) : array
|
||||||
|
{
|
||||||
|
$options['state'] ??= $this->getRandomState();
|
||||||
|
$options['scope'] ??= $this->getDefaultScopes();
|
||||||
|
|
||||||
|
$this->state = $options['state'];
|
||||||
|
|
||||||
|
$options += [
|
||||||
|
'response_type' => 'code',
|
||||||
|
'approval_prompt' => 'auto',
|
||||||
|
];
|
||||||
|
|
||||||
|
if (\is_array($options['scope'])) {
|
||||||
|
$options['scope'] = implode($this->getScopeSeparator(), $options['scope']);
|
||||||
|
}
|
||||||
|
|
||||||
|
$options['redirect_uri'] ??= $this->redirectUri;
|
||||||
|
$options['client_id'] = $this->clientId;
|
||||||
|
|
||||||
|
return $options;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getAuthorizationQuery(array $params) : string
|
||||||
|
{
|
||||||
|
return \http_build_query($params, null, '&', \PHP_QUERY_RFC3986);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getauthorizationUrl(array $options = []) : string
|
||||||
|
{
|
||||||
|
$base = $this->getBaseAuthorizationUrl();
|
||||||
|
$params = $this->getAuthorizationParameters($options);
|
||||||
|
$query = $this->getAuthorizationQuery($params);
|
||||||
|
|
||||||
|
return UriFactory::build($base . '?' . $query);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function authorize(array $options = [], callable $redirectHander = null)
|
||||||
|
{
|
||||||
|
$url = $this->getAuthorizationUrl($options);
|
||||||
|
if ($redirectHander !== null) {
|
||||||
|
return $redirectHandler($url, $this);
|
||||||
|
}
|
||||||
|
|
||||||
|
// @codeCoverageIgnoreStart
|
||||||
|
header('Location: ' . $url);
|
||||||
|
exit;
|
||||||
|
// @codeCoverageIgnoreEnd
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getAccessTokenMethod() : string
|
||||||
|
{
|
||||||
|
return RequestMethod::POST;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getAccessTokenResourceOwnerId() : ?string
|
||||||
|
{
|
||||||
|
return static::ACCESS_TOKEN_RESOURCE_OWNER_ID;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function verifyGrant($grant) : AbstractGrant
|
||||||
|
{
|
||||||
|
$this->grantFactory->checkGrant($grant);
|
||||||
|
|
||||||
|
return $grant;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getAccessTokenUrl(array $params) : string
|
||||||
|
{
|
||||||
|
$url = $this->getBaseAccessTokenUrl($params);
|
||||||
|
|
||||||
|
if ($this->getAccessTokenMethod() === RequestMethod::GET) {
|
||||||
|
$query = $this->getAccessTokenQuery($params);
|
||||||
|
|
||||||
|
return UriFactory::build($ur . '?' . $query);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $url;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getAccessTokenRequest(array $params) : HttpRequest
|
||||||
|
{
|
||||||
|
$method = $this->getAccessTokenMethod();
|
||||||
|
$url = $this->getAccessTokenUrl($params);
|
||||||
|
$options = $this->getoptionProvider->getAccessTokenOptions($this->getAccessTokenMethod(), $params);
|
||||||
|
|
||||||
|
return $this->createRequest($method, $url, null, $options);
|
||||||
|
}
|
||||||
|
|
||||||
|
// string | Grant
|
||||||
|
public function getAccessToken($grant, array $options = []) : AccessTokenInterface
|
||||||
|
{
|
||||||
|
$grant = \is_string($grant) ? $this->grantFactory->getGrant($grant) : $this->verifyGrant();
|
||||||
|
|
||||||
|
$params = [
|
||||||
|
'client_id' => $this->clientId,
|
||||||
|
'client_secret' => $this->clientSecret,
|
||||||
|
'redirect_uri' => $this->redirectUri,
|
||||||
|
];
|
||||||
|
|
||||||
|
$params = $grant->prepareRequestParameters($params, $options);
|
||||||
|
$request = $this->getAccessTokenRequest($params);
|
||||||
|
$response = $this->getParsedResponse($request);
|
||||||
|
|
||||||
|
$prepared = $this->prepareAccessTokenResponse($response);
|
||||||
|
$token = $this->createAccessToken($prepared, $grant);
|
||||||
|
|
||||||
|
return $token;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function createRequest(string $method, string $url, $token, array $options) : HttpRequest
|
||||||
|
{
|
||||||
|
$defaults = [
|
||||||
|
'headers' => $this->getHeaders($token),
|
||||||
|
];
|
||||||
|
|
||||||
|
$options = \array_merge_recursive($defaults, $options);
|
||||||
|
$factory = $this->getRequestFactory();
|
||||||
|
|
||||||
|
return $factory->getRequestWithOptions($method, $url, $options);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getParsedResponse(HttpRequest $request)
|
||||||
|
{
|
||||||
|
$response = $request->rest();
|
||||||
|
$parsed = $this->parseResponse($response);
|
||||||
|
|
||||||
|
$this->checkResponse($response, $parsed);
|
||||||
|
|
||||||
|
return $parsed;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function parseResponse(HttpResponse $response) : array
|
||||||
|
{
|
||||||
|
$content = $response->getBody();
|
||||||
|
$type = \implode(';', (array) $response->getHeader()->get('Content-Type'));
|
||||||
|
|
||||||
|
if (\stripos($type, 'urlencoded') !== false) {
|
||||||
|
\parse_str($content, $parsed);
|
||||||
|
|
||||||
|
return $parsed;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
return \json_decode($content, true);
|
||||||
|
} catch (\Throwable $t) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract protected function checkResponse(HttpResponse $response, $data) : void; // todo: consider to make bool
|
||||||
|
|
||||||
|
protected function prepareAccessTokenResponse(array $result) : array
|
||||||
|
{
|
||||||
|
if (($id = $this->getAccesstokenResourceOwnerId()) !== null) {
|
||||||
|
$result['resource_owner_id'] = ArrayUtils::getArray($id, $result, '.');
|
||||||
|
}
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function createAccessToken(array $response, AbstractGrant $grant) : AccessTokenInterface
|
||||||
|
{
|
||||||
|
return new AccessToken($response);
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract protected function createResourceOwner(array $response, AccessToken $token) : ResourceOwnerInterface;
|
||||||
|
|
||||||
|
public function getResourceOwner(AccessToken $token) : ResourceOwnerInterface
|
||||||
|
{
|
||||||
|
$response = $this->fetchResourceOwnerDetails($token);
|
||||||
|
|
||||||
|
return $this->createResourceOwner($response, $token);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function fetchResourceOwnerDetails(AccessToken $token)
|
||||||
|
{
|
||||||
|
$url = $this->getResourceOwnerDetailsUrl($token);
|
||||||
|
$request = $this->getAuthenticatedRequest(RequestMethod::GET, $url, $token);
|
||||||
|
$response = $this->getParsedResponse($request);
|
||||||
|
|
||||||
|
return $response;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getDefaultHeaders() : array
|
||||||
|
{
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getAuthorizationHeaders($token = null) : array
|
||||||
|
{
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getHeaders($token = null) : array
|
||||||
|
{
|
||||||
|
return $token === null
|
||||||
|
? $this->getDefaultHeaders()
|
||||||
|
: \array_merge($this->getDefaultHeaders(), $this->getAuthorizationHeaders());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
0
Auth/OAuth2/Provider/ResourceOwnerInterface.php
Normal file
0
Auth/OAuth2/Provider/ResourceOwnerInterface.php
Normal file
120
Auth/OAuth2/Token/AccessToken.php
Normal file
120
Auth/OAuth2/Token/AccessToken.php
Normal file
|
|
@ -0,0 +1,120 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Orange Management
|
||||||
|
*
|
||||||
|
* PHP Version 7.4
|
||||||
|
*
|
||||||
|
* @package phpOMS\Auth\OAuth2
|
||||||
|
* @copyright Dennis Eichhorn
|
||||||
|
* @license OMS License 1.0
|
||||||
|
* @version 1.0.0
|
||||||
|
* @link https://orange-management.org
|
||||||
|
*/
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace phpOMS\Auth\OAuth2;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Access token class.
|
||||||
|
*
|
||||||
|
* @package phpOMS\Auth\OAuth2
|
||||||
|
* @license OMS License 1.0
|
||||||
|
* @link https://orange-management.org
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
class AccessToken implements AccessTokenInterface, ResourceOwnerAccessTokenInterface
|
||||||
|
{
|
||||||
|
protected string $accessToken;
|
||||||
|
|
||||||
|
protected ?int $expires = null;
|
||||||
|
|
||||||
|
protected ?string $refreshToken = null;
|
||||||
|
|
||||||
|
protected ?string $resourceOwnerId = null;
|
||||||
|
|
||||||
|
protected array $values = [];
|
||||||
|
|
||||||
|
public function __construct(array $options = [])
|
||||||
|
{
|
||||||
|
if (!isset($options['access_token'])) {
|
||||||
|
throw new \InvalidArgumentException();
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->accessToken = $options['access_token'];
|
||||||
|
|
||||||
|
if (isset($options['resource_owner_id'])) {
|
||||||
|
$this->resourceOwnerId = $options['resource_owner_id'];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($options['refresh_token'])) {
|
||||||
|
$this->refreshToken = $options['refresh_token'];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($options['expires_in'])) {
|
||||||
|
$this->expires = $options['expires_in'] !== 0 ? \time() + $options['expires_in'] : 0;
|
||||||
|
} elseif (!empty($options['expires'])) {
|
||||||
|
$this->expires = $options['expires'];
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->values = \array_diff_key($options, \array_flip([
|
||||||
|
'access_token',
|
||||||
|
'resource_owner_id',
|
||||||
|
'refresh_token',
|
||||||
|
'expires_in',
|
||||||
|
'expires',
|
||||||
|
]));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getToken() : string
|
||||||
|
{
|
||||||
|
return $this->accessToken;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getExpires() : ?int
|
||||||
|
{
|
||||||
|
return $this->expires;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getRefreshToken() : ?string
|
||||||
|
{
|
||||||
|
return $this->refreshToken;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getResourceOwnerId() : ?string
|
||||||
|
{
|
||||||
|
return $this->resourceOwnerId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function hasExpired() : bool
|
||||||
|
{
|
||||||
|
return $this->expires < \time();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function __toString()
|
||||||
|
{
|
||||||
|
return $this->getToken();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function jsonSerialize()
|
||||||
|
{
|
||||||
|
$params = $this->values;
|
||||||
|
|
||||||
|
if (isset($this->accessToken)) {
|
||||||
|
$params['access_token'] = $this->accessToken;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($this->refreshToken)) {
|
||||||
|
$params['refresh_token'] = $this->refreshToken;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($this->expires)) {
|
||||||
|
$params['expires'] = $this->expires;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($this->resourceOwnerId)) {
|
||||||
|
$params['resource_owner_id'] = $this->resourceOwnerId;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $params;
|
||||||
|
}
|
||||||
|
}
|
||||||
41
Auth/OAuth2/Token/AccessTokenInterface.php
Normal file
41
Auth/OAuth2/Token/AccessTokenInterface.php
Normal file
|
|
@ -0,0 +1,41 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Orange Management
|
||||||
|
*
|
||||||
|
* PHP Version 7.4
|
||||||
|
*
|
||||||
|
* @package phpOMS\Auth\OAuth2\Token
|
||||||
|
* @copyright Dennis Eichhorn
|
||||||
|
* @license OMS License 1.0
|
||||||
|
* @version 1.0.0
|
||||||
|
* @link https://orange-management.org
|
||||||
|
* @see https://tools.ietf.org/html/rfc6749
|
||||||
|
*/
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace phpOMS\Auth\OAuth2\Token;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provider class.
|
||||||
|
*
|
||||||
|
* @package phpOMS\Auth\OAuth2\Token
|
||||||
|
* @license OMS License 1.0
|
||||||
|
* @link https://orange-management.org
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
interface AccessTokenInterface extends \JsonSerializable
|
||||||
|
{
|
||||||
|
public function getToken() : string;
|
||||||
|
|
||||||
|
public function getRefreshToken() : ?string;
|
||||||
|
|
||||||
|
public function getExpires() : ?int;
|
||||||
|
|
||||||
|
public function hasExpired() : bool;
|
||||||
|
|
||||||
|
public function getValues() : array;
|
||||||
|
|
||||||
|
public function __toString();
|
||||||
|
|
||||||
|
public function jsonSerialize();
|
||||||
|
}
|
||||||
|
|
@ -4,24 +4,26 @@
|
||||||
*
|
*
|
||||||
* PHP Version 7.4
|
* PHP Version 7.4
|
||||||
*
|
*
|
||||||
* @package phpOMS\Auth\OAuth2
|
* @package phpOMS\Auth\OAuth2\Token
|
||||||
* @copyright Dennis Eichhorn
|
* @copyright Dennis Eichhorn
|
||||||
* @license OMS License 1.0
|
* @license OMS License 1.0
|
||||||
* @version 1.0.0
|
* @version 1.0.0
|
||||||
* @link https://orange-management.org
|
* @link https://orange-management.org
|
||||||
|
* @see https://tools.ietf.org/html/rfc6749
|
||||||
*/
|
*/
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace phpOMS\Auth\OAuth2;
|
namespace phpOMS\Auth\OAuth2\Token;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Access token class.
|
* Provider class.
|
||||||
*
|
*
|
||||||
* @package phpOMS\Auth\OAuth2
|
* @package phpOMS\Auth\OAuth2\Token
|
||||||
* @license OMS License 1.0
|
* @license OMS License 1.0
|
||||||
* @link https://orange-management.org
|
* @link https://orange-management.org
|
||||||
* @since 1.0.0
|
* @since 1.0.0
|
||||||
*/
|
*/
|
||||||
final class AccessToken
|
interface ResourceOwnerAccessTokenInterface extends AccessTokenInterface
|
||||||
{
|
{
|
||||||
|
public function getResourceOwnerId() : ?string;
|
||||||
}
|
}
|
||||||
|
|
@ -1,27 +0,0 @@
|
||||||
<?php
|
|
||||||
/**
|
|
||||||
* Orange Management
|
|
||||||
*
|
|
||||||
* PHP Version 7.4
|
|
||||||
*
|
|
||||||
* @package phpOMS\Auth\OAuth2
|
|
||||||
* @copyright Dennis Eichhorn
|
|
||||||
* @license OMS License 1.0
|
|
||||||
* @version 1.0.0
|
|
||||||
* @link https://orange-management.org
|
|
||||||
*/
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace phpOMS\Auth\OAuth2;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Token storage interface.
|
|
||||||
*
|
|
||||||
* @package phpOMS\Auth\OAuth2
|
|
||||||
* @license OMS License 1.0
|
|
||||||
* @link https://orange-management.org
|
|
||||||
* @since 1.0.0
|
|
||||||
*/
|
|
||||||
interface TokenStorageInterface
|
|
||||||
{
|
|
||||||
}
|
|
||||||
Loading…
Reference in New Issue
Block a user