Initial commit: CloudOps infrastructure platform
This commit is contained in:
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Mautic\IntegrationsBundle\Auth\Provider\ApiKey\Credentials;
|
||||
|
||||
use Mautic\IntegrationsBundle\Auth\Provider\AuthCredentialsInterface;
|
||||
|
||||
interface HeaderCredentialsInterface extends AuthCredentialsInterface
|
||||
{
|
||||
public function getKeyName(): string;
|
||||
|
||||
public function getApiKey(): ?string;
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Mautic\IntegrationsBundle\Auth\Provider\ApiKey\Credentials;
|
||||
|
||||
use Mautic\IntegrationsBundle\Auth\Provider\AuthCredentialsInterface;
|
||||
|
||||
interface ParameterCredentialsInterface extends AuthCredentialsInterface
|
||||
{
|
||||
public function getKeyName(): string;
|
||||
|
||||
public function getApiKey(): ?string;
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Mautic\IntegrationsBundle\Auth\Provider\ApiKey;
|
||||
|
||||
use GuzzleHttp\Client;
|
||||
use GuzzleHttp\ClientInterface;
|
||||
use GuzzleHttp\Handler\CurlHandler;
|
||||
use GuzzleHttp\HandlerStack;
|
||||
use GuzzleHttp\Middleware;
|
||||
use GuzzleHttp\Psr7\Request;
|
||||
use GuzzleHttp\Psr7\Uri;
|
||||
use Mautic\IntegrationsBundle\Auth\Provider\ApiKey\Credentials\HeaderCredentialsInterface;
|
||||
use Mautic\IntegrationsBundle\Auth\Provider\ApiKey\Credentials\ParameterCredentialsInterface;
|
||||
use Mautic\IntegrationsBundle\Auth\Provider\AuthConfigInterface;
|
||||
use Mautic\IntegrationsBundle\Auth\Provider\AuthCredentialsInterface;
|
||||
use Mautic\IntegrationsBundle\Auth\Provider\AuthProviderInterface;
|
||||
use Mautic\IntegrationsBundle\Exception\InvalidCredentialsException;
|
||||
use Mautic\IntegrationsBundle\Exception\PluginNotConfiguredException;
|
||||
|
||||
/**
|
||||
* Factory for building HTTP clients using basic auth.
|
||||
*/
|
||||
class HttpFactory implements AuthProviderInterface
|
||||
{
|
||||
public const NAME = 'api_key';
|
||||
|
||||
/**
|
||||
* Cache of initialized clients.
|
||||
*
|
||||
* @var Client[]
|
||||
*/
|
||||
private array $initializedClients = [];
|
||||
|
||||
private HeaderCredentialsInterface|ParameterCredentialsInterface|null $credentials = null;
|
||||
|
||||
public function getAuthType(): string
|
||||
{
|
||||
return self::NAME;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param HeaderCredentialsInterface|ParameterCredentialsInterface $credentials
|
||||
*
|
||||
* @throws PluginNotConfiguredException
|
||||
* @throws InvalidCredentialsException
|
||||
*/
|
||||
public function getClient(AuthCredentialsInterface $credentials, ?AuthConfigInterface $config = null): ClientInterface
|
||||
{
|
||||
if (!$this->credentialsAreValid($credentials)) {
|
||||
throw new InvalidCredentialsException(sprintf('Credentials must implement either the %s or %s interfaces', HeaderCredentialsInterface::class, ParameterCredentialsInterface::class));
|
||||
}
|
||||
|
||||
if (!$this->credentialsAreConfigured($credentials)) {
|
||||
throw new PluginNotConfiguredException('API key is missing');
|
||||
}
|
||||
|
||||
// Return cached initialized client if there is one.
|
||||
if (!empty($this->initializedClients[$credentials->getKeyName()])) {
|
||||
return $this->initializedClients[$credentials->getKeyName()];
|
||||
}
|
||||
|
||||
$this->credentials = $credentials;
|
||||
|
||||
if ($credentials instanceof HeaderCredentialsInterface) {
|
||||
$this->initializedClients[$credentials->getKeyName()] = $this->getHeaderClient();
|
||||
|
||||
return $this->initializedClients[$credentials->getKeyName()];
|
||||
}
|
||||
|
||||
$this->initializedClients[$credentials->getKeyName()] = $this->getParameterClient();
|
||||
|
||||
return $this->initializedClients[$credentials->getKeyName()];
|
||||
}
|
||||
|
||||
private function credentialsAreValid(AuthCredentialsInterface $credentials): bool
|
||||
{
|
||||
return $credentials instanceof HeaderCredentialsInterface || $credentials instanceof ParameterCredentialsInterface;
|
||||
}
|
||||
|
||||
private function credentialsAreConfigured(AuthCredentialsInterface $credentials): bool
|
||||
{
|
||||
return !empty($credentials->getApiKey());
|
||||
}
|
||||
|
||||
private function getHeaderClient(): ClientInterface
|
||||
{
|
||||
return new Client(
|
||||
[
|
||||
'headers' => [$this->credentials->getKeyName() => $this->credentials->getApiKey()],
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
private function getParameterClient(): ClientInterface
|
||||
{
|
||||
$handler = new HandlerStack();
|
||||
$handler->setHandler(new CurlHandler());
|
||||
|
||||
$handler->unshift(
|
||||
Middleware::mapRequest(
|
||||
fn (Request $request) => $request->withUri(
|
||||
Uri::withQueryValue($request->getUri(), $this->credentials->getKeyName(), $this->credentials->getApiKey())
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
return new Client(
|
||||
[
|
||||
'handler' => $handler,
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Mautic\IntegrationsBundle\Auth\Provider;
|
||||
|
||||
interface AuthConfigInterface
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Mautic\IntegrationsBundle\Auth\Provider;
|
||||
|
||||
interface AuthCredentialsInterface
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Mautic\IntegrationsBundle\Auth\Provider;
|
||||
|
||||
use GuzzleHttp\ClientInterface;
|
||||
|
||||
interface AuthProviderInterface
|
||||
{
|
||||
public function getAuthType(): string;
|
||||
|
||||
public function getClient(AuthCredentialsInterface $credentials, ?AuthConfigInterface $config = null): ClientInterface;
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Mautic\IntegrationsBundle\Auth\Provider\BasicAuth;
|
||||
|
||||
use Mautic\IntegrationsBundle\Auth\Provider\AuthCredentialsInterface;
|
||||
|
||||
interface CredentialsInterface extends AuthCredentialsInterface
|
||||
{
|
||||
public function getUsername(): ?string;
|
||||
|
||||
public function getPassword(): ?string;
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Mautic\IntegrationsBundle\Auth\Provider\BasicAuth;
|
||||
|
||||
use GuzzleHttp\Client;
|
||||
use GuzzleHttp\ClientInterface;
|
||||
use Mautic\IntegrationsBundle\Auth\Provider\AuthConfigInterface;
|
||||
use Mautic\IntegrationsBundle\Auth\Provider\AuthCredentialsInterface;
|
||||
use Mautic\IntegrationsBundle\Auth\Provider\AuthProviderInterface;
|
||||
use Mautic\IntegrationsBundle\Exception\PluginNotConfiguredException;
|
||||
|
||||
/**
|
||||
* Factory for building HTTP clients using basic auth.
|
||||
*/
|
||||
class HttpFactory implements AuthProviderInterface
|
||||
{
|
||||
public const NAME = 'basic_auth';
|
||||
|
||||
/**
|
||||
* Cache of initialized clients.
|
||||
*
|
||||
* @var Client[]
|
||||
*/
|
||||
private array $initializedClients = [];
|
||||
|
||||
public function getAuthType(): string
|
||||
{
|
||||
return self::NAME;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws PluginNotConfiguredException
|
||||
*/
|
||||
public function getClient(AuthCredentialsInterface $credentials, ?AuthConfigInterface $config = null): ClientInterface
|
||||
{
|
||||
if (!$this->credentialsAreConfigured($credentials)) {
|
||||
throw new PluginNotConfiguredException('Username and/or password is missing');
|
||||
}
|
||||
|
||||
// Return cached initialized client if there is one.
|
||||
if (!empty($this->initializedClients[$credentials->getUsername()])) {
|
||||
return $this->initializedClients[$credentials->getUsername()];
|
||||
}
|
||||
|
||||
$this->initializedClients[$credentials->getUsername()] = new Client(
|
||||
[
|
||||
'auth' => [
|
||||
$credentials->getUsername(),
|
||||
$credentials->getPassword(),
|
||||
],
|
||||
]
|
||||
);
|
||||
|
||||
return $this->initializedClients[$credentials->getUsername()];
|
||||
}
|
||||
|
||||
protected function credentialsAreConfigured(CredentialsInterface $credentials): bool
|
||||
{
|
||||
return $credentials->getUsername() && $credentials->getPassword();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Mautic\IntegrationsBundle\Auth\Provider\Oauth1aThreeLegged;
|
||||
|
||||
use Mautic\IntegrationsBundle\Auth\Provider\AuthCredentialsInterface;
|
||||
|
||||
interface CredentialsInterface extends AuthCredentialsInterface
|
||||
{
|
||||
public function getAuthorizationUrl(): string;
|
||||
|
||||
public function getRequestTokenUrl(): string;
|
||||
|
||||
public function getAccessTokenUrl(): string;
|
||||
|
||||
public function getAuthCallbackUrl(): ?string;
|
||||
|
||||
public function getConsumerId(): ?string;
|
||||
|
||||
public function getConsumerSecret(): ?string;
|
||||
|
||||
public function getAccessToken(): ?string;
|
||||
|
||||
public function getRequestToken(): ?string;
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Mautic\IntegrationsBundle\Auth\Provider\Oauth1aTwoLegged;
|
||||
|
||||
use Mautic\IntegrationsBundle\Auth\Provider\AuthCredentialsInterface;
|
||||
|
||||
interface CredentialsInterface extends AuthCredentialsInterface
|
||||
{
|
||||
public function getAuthUrl(): string;
|
||||
|
||||
public function getConsumerKey(): ?string;
|
||||
|
||||
public function getConsumerSecret(): ?string;
|
||||
|
||||
public function getToken(): ?string;
|
||||
|
||||
public function getTokenSecret(): ?string;
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Mautic\IntegrationsBundle\Auth\Provider\Oauth1aTwoLegged;
|
||||
|
||||
use GuzzleHttp\Client;
|
||||
use GuzzleHttp\ClientInterface;
|
||||
use GuzzleHttp\HandlerStack;
|
||||
use GuzzleHttp\Subscriber\Oauth\Oauth1;
|
||||
use Mautic\IntegrationsBundle\Auth\Provider\AuthConfigInterface;
|
||||
use Mautic\IntegrationsBundle\Auth\Provider\AuthCredentialsInterface;
|
||||
use Mautic\IntegrationsBundle\Auth\Provider\AuthProviderInterface;
|
||||
use Mautic\IntegrationsBundle\Exception\PluginNotConfiguredException;
|
||||
|
||||
/**
|
||||
* Factory for building HTTP clients that will sign the requests with Oauth1a headers.
|
||||
*/
|
||||
class HttpFactory implements AuthProviderInterface
|
||||
{
|
||||
public const NAME = 'oauth1a_two_legged';
|
||||
|
||||
/**
|
||||
* Cache of initialized clients.
|
||||
*
|
||||
* @var Client[]
|
||||
*/
|
||||
private array $initializedClients = [];
|
||||
|
||||
public function getAuthType(): string
|
||||
{
|
||||
return self::NAME;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws PluginNotConfiguredException
|
||||
*/
|
||||
public function getClient(AuthCredentialsInterface $credentials, ?AuthConfigInterface $config = null): ClientInterface
|
||||
{
|
||||
// Return cached initialized client if there is one.
|
||||
if (!empty($this->initializedClients[$credentials->getConsumerKey()])) {
|
||||
return $this->initializedClients[$credentials->getConsumerKey()];
|
||||
}
|
||||
|
||||
if (!$this->credentialsAreConfigured($credentials)) {
|
||||
throw new PluginNotConfiguredException('Oauth1a Credentials or URL is missing');
|
||||
}
|
||||
|
||||
$this->initializedClients[$credentials->getConsumerKey()] = $this->buildClient($credentials);
|
||||
|
||||
return $this->initializedClients[$credentials->getConsumerKey()];
|
||||
}
|
||||
|
||||
private function buildClient(CredentialsInterface $credentials): Client
|
||||
{
|
||||
$stack = HandlerStack::create();
|
||||
$stack->push($this->createOauth1($credentials));
|
||||
|
||||
return new Client(
|
||||
[
|
||||
'handler' => $stack,
|
||||
'base_uri' => $credentials->getAuthUrl(),
|
||||
'auth' => 'oauth',
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
private function createOauth1(CredentialsInterface $credentials): Oauth1
|
||||
{
|
||||
$config = [
|
||||
'consumer_key' => $credentials->getConsumerKey(),
|
||||
'consumer_secret' => $credentials->getConsumerSecret(),
|
||||
];
|
||||
|
||||
if ($credentials->getToken() && $credentials->getTokenSecret()) {
|
||||
$config['token'] = $credentials->getToken();
|
||||
$config['token_secret'] = $credentials->getTokenSecret();
|
||||
}
|
||||
|
||||
return new Oauth1($config);
|
||||
}
|
||||
|
||||
private function credentialsAreConfigured(CredentialsInterface $credentials): bool
|
||||
{
|
||||
return !empty($credentials->getAuthUrl()) && !empty($credentials->getConsumerKey()) && !empty($credentials->getConsumerSecret());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Mautic\IntegrationsBundle\Auth\Provider\Oauth2ThreeLegged\Credentials;
|
||||
|
||||
use Mautic\IntegrationsBundle\Auth\Provider\AuthCredentialsInterface;
|
||||
|
||||
interface AccessTokenInterface extends AuthCredentialsInterface
|
||||
{
|
||||
public function getAccessToken(): ?string;
|
||||
|
||||
public function getAccessTokenExpiry(): ?\DateTimeImmutable;
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Mautic\IntegrationsBundle\Auth\Provider\Oauth2ThreeLegged\Credentials;
|
||||
|
||||
interface CodeInterface
|
||||
{
|
||||
public function getCode(): ?string;
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Mautic\IntegrationsBundle\Auth\Provider\Oauth2ThreeLegged\Credentials;
|
||||
|
||||
use Mautic\IntegrationsBundle\Auth\Provider\AuthCredentialsInterface;
|
||||
|
||||
interface CredentialsInterface extends AuthCredentialsInterface
|
||||
{
|
||||
public function getAuthorizationUrl(): string;
|
||||
|
||||
public function getTokenUrl(): string;
|
||||
|
||||
public function getClientId(): ?string;
|
||||
|
||||
public function getClientSecret(): ?string;
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Mautic\IntegrationsBundle\Auth\Provider\Oauth2ThreeLegged\Credentials;
|
||||
|
||||
interface RedirectUriInterface
|
||||
{
|
||||
public function getRedirectUri(): string;
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Mautic\IntegrationsBundle\Auth\Provider\Oauth2ThreeLegged\Credentials;
|
||||
|
||||
use Mautic\IntegrationsBundle\Auth\Provider\AuthCredentialsInterface;
|
||||
|
||||
interface RefreshTokenInterface extends AuthCredentialsInterface
|
||||
{
|
||||
public function getRefreshToken(): ?string;
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Mautic\IntegrationsBundle\Auth\Provider\Oauth2ThreeLegged\Credentials;
|
||||
|
||||
interface ScopeInterface
|
||||
{
|
||||
public function getScope(): ?string;
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Mautic\IntegrationsBundle\Auth\Provider\Oauth2ThreeLegged\Credentials;
|
||||
|
||||
interface StateInterface
|
||||
{
|
||||
public function getState(): ?string;
|
||||
}
|
||||
@@ -0,0 +1,182 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Mautic\IntegrationsBundle\Auth\Provider\Oauth2ThreeLegged;
|
||||
|
||||
use GuzzleHttp\Client;
|
||||
use GuzzleHttp\ClientInterface;
|
||||
use GuzzleHttp\HandlerStack;
|
||||
use kamermans\OAuth2\GrantType\AuthorizationCode;
|
||||
use kamermans\OAuth2\GrantType\RefreshToken;
|
||||
use kamermans\OAuth2\OAuth2Middleware;
|
||||
use Mautic\IntegrationsBundle\Auth\Provider\AuthConfigInterface;
|
||||
use Mautic\IntegrationsBundle\Auth\Provider\AuthCredentialsInterface;
|
||||
use Mautic\IntegrationsBundle\Auth\Provider\AuthProviderInterface;
|
||||
use Mautic\IntegrationsBundle\Auth\Provider\Oauth2ThreeLegged\Credentials\CodeInterface;
|
||||
use Mautic\IntegrationsBundle\Auth\Provider\Oauth2ThreeLegged\Credentials\CredentialsInterface;
|
||||
use Mautic\IntegrationsBundle\Auth\Provider\Oauth2ThreeLegged\Credentials\RedirectUriInterface;
|
||||
use Mautic\IntegrationsBundle\Auth\Provider\Oauth2ThreeLegged\Credentials\ScopeInterface;
|
||||
use Mautic\IntegrationsBundle\Auth\Support\Oauth2\ConfigAccess\ConfigCredentialsSignerInterface;
|
||||
use Mautic\IntegrationsBundle\Auth\Support\Oauth2\ConfigAccess\ConfigTokenFactoryInterface;
|
||||
use Mautic\IntegrationsBundle\Auth\Support\Oauth2\ConfigAccess\ConfigTokenPersistenceInterface;
|
||||
use Mautic\IntegrationsBundle\Auth\Support\Oauth2\ConfigAccess\ConfigTokenSignerInterface;
|
||||
use Mautic\IntegrationsBundle\Exception\PluginNotConfiguredException;
|
||||
|
||||
/**
|
||||
* Factory for building HTTP clients that will sign the requests with Oauth2 headers.
|
||||
* Based on Guzzle OAuth 2.0 Subscriber - kamermans/guzzle-oauth2-subscriber package.
|
||||
*
|
||||
* @see https://github.com/kamermans/guzzle-oauth2-subscriber
|
||||
*/
|
||||
class HttpFactory implements AuthProviderInterface
|
||||
{
|
||||
public const NAME = 'oauth2_three_legged';
|
||||
|
||||
private ?AuthCredentialsInterface $credentials = null;
|
||||
|
||||
private ConfigCredentialsSignerInterface|ConfigTokenPersistenceInterface|ConfigTokenSignerInterface|AuthConfigInterface|null $config = null;
|
||||
|
||||
private ?Client $reAuthClient = null;
|
||||
|
||||
/**
|
||||
* Cache of initialized clients.
|
||||
*
|
||||
* @var Client[]
|
||||
*/
|
||||
private array $initializedClients = [];
|
||||
|
||||
public function getAuthType(): string
|
||||
{
|
||||
return self::NAME;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ConfigCredentialsSignerInterface|ConfigTokenPersistenceInterface|ConfigTokenSignerInterface|AuthConfigInterface $config
|
||||
*
|
||||
* @throws PluginNotConfiguredException
|
||||
*/
|
||||
public function getClient(AuthCredentialsInterface $credentials, ?AuthConfigInterface $config = null): ClientInterface
|
||||
{
|
||||
if (!$this->credentialsAreConfigured($credentials)) {
|
||||
throw new PluginNotConfiguredException('Missing credentials');
|
||||
}
|
||||
|
||||
// Return cached initialized client if there is one.
|
||||
if (isset($this->initializedClients[$credentials->getClientId()])) {
|
||||
return $this->initializedClients[$credentials->getClientId()];
|
||||
}
|
||||
|
||||
$this->credentials = $credentials;
|
||||
$this->config = $config;
|
||||
|
||||
$options = [
|
||||
'handler' => $this->getStackHandler(),
|
||||
'auth' => 'oauth',
|
||||
];
|
||||
|
||||
// Set up base URI if it's configured.
|
||||
if (method_exists($credentials, 'getBaseUri') && ($baseUri = $credentials->getBaseUri()) !== null) {
|
||||
$options['base_uri'] = $baseUri;
|
||||
}
|
||||
|
||||
$this->initializedClients[$credentials->getClientId()] = new Client($options);
|
||||
|
||||
return $this->initializedClients[$credentials->getClientId()];
|
||||
}
|
||||
|
||||
protected function credentialsAreConfigured(CredentialsInterface $credentials): bool
|
||||
{
|
||||
if (empty($credentials->getAuthorizationUrl())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (empty($credentials->getTokenUrl())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (empty($credentials->getClientId())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (empty($credentials->getClientSecret())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private function getStackHandler(): HandlerStack
|
||||
{
|
||||
$reAuthConfig = $this->getReAuthConfig();
|
||||
$grantType = new AuthorizationCode($this->getReAuthClient(), $reAuthConfig);
|
||||
$refreshTokenGrantType = new RefreshToken($this->getReAuthClient(), $reAuthConfig);
|
||||
$middleware = new OAuth2Middleware($grantType, $refreshTokenGrantType);
|
||||
|
||||
$this->configureMiddleware($middleware);
|
||||
|
||||
$stack = HandlerStack::create();
|
||||
$stack->push($middleware);
|
||||
|
||||
return $stack;
|
||||
}
|
||||
|
||||
private function getReAuthClient(): ClientInterface
|
||||
{
|
||||
if ($this->reAuthClient) {
|
||||
return $this->reAuthClient;
|
||||
}
|
||||
|
||||
$this->reAuthClient = new Client([
|
||||
'base_uri' => $this->credentials->getTokenUrl(),
|
||||
]);
|
||||
|
||||
return $this->reAuthClient;
|
||||
}
|
||||
|
||||
private function getReAuthConfig(): array
|
||||
{
|
||||
$config = [
|
||||
'client_id' => $this->credentials->getClientId(),
|
||||
'client_secret' => $this->credentials->getClientSecret(),
|
||||
'code' => '',
|
||||
];
|
||||
|
||||
if ($this->credentials instanceof ScopeInterface) {
|
||||
$config['scope'] = $this->credentials->getScope();
|
||||
}
|
||||
|
||||
if ($this->credentials instanceof RedirectUriInterface) {
|
||||
$config['redirect_uri'] = $this->credentials->getRedirectUri();
|
||||
}
|
||||
|
||||
if ($this->credentials instanceof CodeInterface) {
|
||||
$config['code'] = $this->credentials->getCode();
|
||||
}
|
||||
|
||||
return $config;
|
||||
}
|
||||
|
||||
private function configureMiddleware(OAuth2Middleware $oauth): void
|
||||
{
|
||||
if (!$this->config) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($this->config instanceof ConfigCredentialsSignerInterface) {
|
||||
$oauth->setClientCredentialsSigner($this->config->getCredentialsSigner());
|
||||
}
|
||||
|
||||
if ($this->config instanceof ConfigTokenPersistenceInterface) {
|
||||
$oauth->setTokenPersistence($this->config->getTokenPersistence());
|
||||
}
|
||||
|
||||
if ($this->config instanceof ConfigTokenSignerInterface) {
|
||||
$oauth->setAccessTokenSigner($this->config->getTokenSigner());
|
||||
}
|
||||
|
||||
if ($this->config instanceof ConfigTokenFactoryInterface) {
|
||||
$oauth->setTokenFactory($this->config->getTokenFactory());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Mautic\IntegrationsBundle\Auth\Provider\Oauth2TwoLegged\Credentials;
|
||||
|
||||
use Mautic\IntegrationsBundle\Auth\Provider\AuthCredentialsInterface;
|
||||
|
||||
interface ClientCredentialsGrantInterface extends AuthCredentialsInterface
|
||||
{
|
||||
public function getAuthorizationUrl(): string;
|
||||
|
||||
public function getClientId(): ?string;
|
||||
|
||||
public function getClientSecret(): ?string;
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Mautic\IntegrationsBundle\Auth\Provider\Oauth2TwoLegged\Credentials;
|
||||
|
||||
use Mautic\IntegrationsBundle\Auth\Provider\AuthCredentialsInterface;
|
||||
|
||||
interface PasswordCredentialsGrantInterface extends AuthCredentialsInterface
|
||||
{
|
||||
public function getAuthorizationUrl(): string;
|
||||
|
||||
public function getClientId(): ?string;
|
||||
|
||||
public function getClientSecret(): ?string;
|
||||
|
||||
public function getUsername(): ?string;
|
||||
|
||||
public function getPassword(): ?string;
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Mautic\IntegrationsBundle\Auth\Provider\Oauth2TwoLegged\Credentials;
|
||||
|
||||
interface ScopeInterface
|
||||
{
|
||||
public function getScope(): ?string;
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Mautic\IntegrationsBundle\Auth\Provider\Oauth2TwoLegged\Credentials;
|
||||
|
||||
interface StateInterface
|
||||
{
|
||||
public function getState(): ?string;
|
||||
}
|
||||
@@ -0,0 +1,196 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Mautic\IntegrationsBundle\Auth\Provider\Oauth2TwoLegged;
|
||||
|
||||
use GuzzleHttp\Client;
|
||||
use GuzzleHttp\ClientInterface;
|
||||
use GuzzleHttp\HandlerStack;
|
||||
use kamermans\OAuth2\GrantType\ClientCredentials;
|
||||
use kamermans\OAuth2\GrantType\GrantTypeInterface;
|
||||
use kamermans\OAuth2\GrantType\PasswordCredentials;
|
||||
use kamermans\OAuth2\GrantType\RefreshToken;
|
||||
use kamermans\OAuth2\OAuth2Middleware;
|
||||
use Mautic\IntegrationsBundle\Auth\Provider\AuthConfigInterface;
|
||||
use Mautic\IntegrationsBundle\Auth\Provider\AuthCredentialsInterface;
|
||||
use Mautic\IntegrationsBundle\Auth\Provider\AuthProviderInterface;
|
||||
use Mautic\IntegrationsBundle\Auth\Provider\Oauth2TwoLegged\Credentials\ClientCredentialsGrantInterface;
|
||||
use Mautic\IntegrationsBundle\Auth\Provider\Oauth2TwoLegged\Credentials\PasswordCredentialsGrantInterface;
|
||||
use Mautic\IntegrationsBundle\Auth\Provider\Oauth2TwoLegged\Credentials\ScopeInterface;
|
||||
use Mautic\IntegrationsBundle\Auth\Provider\Oauth2TwoLegged\Credentials\StateInterface;
|
||||
use Mautic\IntegrationsBundle\Auth\Support\Oauth2\ConfigAccess\ConfigCredentialsSignerInterface;
|
||||
use Mautic\IntegrationsBundle\Auth\Support\Oauth2\ConfigAccess\ConfigTokenFactoryInterface;
|
||||
use Mautic\IntegrationsBundle\Auth\Support\Oauth2\ConfigAccess\ConfigTokenPersistenceInterface;
|
||||
use Mautic\IntegrationsBundle\Auth\Support\Oauth2\ConfigAccess\ConfigTokenSignerInterface;
|
||||
use Mautic\IntegrationsBundle\Exception\InvalidCredentialsException;
|
||||
use Mautic\IntegrationsBundle\Exception\PluginNotConfiguredException;
|
||||
|
||||
/**
|
||||
* Factory for building HTTP clients that will sign the requests with Oauth2 headers.
|
||||
* Based on Guzzle OAuth 2.0 Subscriber - kamermans/guzzle-oauth2-subscriber package.
|
||||
*
|
||||
* @see https://github.com/kamermans/guzzle-oauth2-subscriber
|
||||
*/
|
||||
class HttpFactory implements AuthProviderInterface
|
||||
{
|
||||
public const NAME = 'oauth2_two_legged';
|
||||
|
||||
private PasswordCredentialsGrantInterface|ClientCredentialsGrantInterface|null $credentials = null;
|
||||
|
||||
private ConfigCredentialsSignerInterface|ConfigTokenPersistenceInterface|ConfigTokenSignerInterface|AuthConfigInterface|ConfigTokenFactoryInterface|null $config = null;
|
||||
|
||||
private ?Client $reAuthClient = null;
|
||||
|
||||
/**
|
||||
* Cache of initialized clients.
|
||||
*
|
||||
* @var Client[]
|
||||
*/
|
||||
private array $initializedClients = [];
|
||||
|
||||
public function getAuthType(): string
|
||||
{
|
||||
return self::NAME;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param PasswordCredentialsGrantInterface|ClientCredentialsGrantInterface $credentials
|
||||
* @param ConfigCredentialsSignerInterface|ConfigTokenPersistenceInterface|ConfigTokenSignerInterface|AuthConfigInterface|ConfigTokenFactoryInterface $config
|
||||
*
|
||||
* @throws PluginNotConfiguredException
|
||||
* @throws InvalidCredentialsException
|
||||
*/
|
||||
public function getClient(AuthCredentialsInterface $credentials, ?AuthConfigInterface $config = null): ClientInterface
|
||||
{
|
||||
if (!$this->credentialsAreValid($credentials)) {
|
||||
throw new InvalidCredentialsException(sprintf('Credentials must implement either the %s or %s interfaces', PasswordCredentialsGrantInterface::class, ClientCredentialsGrantInterface::class));
|
||||
}
|
||||
|
||||
if (!$this->credentialsAreConfigured($credentials)) {
|
||||
throw new PluginNotConfiguredException('Authorization URL, client ID or client secret is missing');
|
||||
}
|
||||
|
||||
// Return cached initialized client if there is one.
|
||||
if (!empty($this->initializedClients[$credentials->getClientId()])) {
|
||||
return $this->initializedClients[$credentials->getClientId()];
|
||||
}
|
||||
|
||||
$this->credentials = $credentials;
|
||||
$this->config = $config;
|
||||
|
||||
$this->initializedClients[$credentials->getClientId()] = new Client(
|
||||
[
|
||||
'handler' => $this->getStackHandler(),
|
||||
'auth' => 'oauth',
|
||||
]
|
||||
);
|
||||
|
||||
return $this->initializedClients[$credentials->getClientId()];
|
||||
}
|
||||
|
||||
private function credentialsAreValid(AuthCredentialsInterface $credentials): bool
|
||||
{
|
||||
return $credentials instanceof PasswordCredentialsGrantInterface || $credentials instanceof ClientCredentialsGrantInterface;
|
||||
}
|
||||
|
||||
private function credentialsAreConfigured(AuthCredentialsInterface $credentials): bool
|
||||
{
|
||||
if (empty($credentials->getAuthorizationUrl()) || empty($credentials->getClientId()) || empty($credentials->getClientSecret())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($credentials instanceof PasswordCredentialsGrantInterface && (empty($credentials->getUsername()) || empty($credentials->getPassword()))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private function getStackHandler(): HandlerStack
|
||||
{
|
||||
$reAuthConfig = $this->getReAuthConfig();
|
||||
$accessTokenGrantType = $this->getGrantType($reAuthConfig);
|
||||
$refreshTokenGrantType = new RefreshToken($this->getReAuthClient(), $reAuthConfig);
|
||||
$middleware = new OAuth2Middleware($accessTokenGrantType, $refreshTokenGrantType);
|
||||
|
||||
$this->configureMiddleware($middleware);
|
||||
|
||||
$stack = HandlerStack::create();
|
||||
$stack->push($middleware);
|
||||
|
||||
return $stack;
|
||||
}
|
||||
|
||||
private function getReAuthClient(): ClientInterface
|
||||
{
|
||||
if ($this->reAuthClient) {
|
||||
return $this->reAuthClient;
|
||||
}
|
||||
|
||||
$this->reAuthClient = new Client(
|
||||
[
|
||||
'base_uri' => $this->credentials->getAuthorizationUrl(),
|
||||
]
|
||||
);
|
||||
|
||||
return $this->reAuthClient;
|
||||
}
|
||||
|
||||
private function getReAuthConfig(): array
|
||||
{
|
||||
$config = [
|
||||
'client_id' => $this->credentials->getClientId(),
|
||||
'client_secret' => $this->credentials->getClientSecret(),
|
||||
];
|
||||
|
||||
if ($this->credentials instanceof ScopeInterface) {
|
||||
$config['scope'] = $this->credentials->getScope();
|
||||
}
|
||||
|
||||
if ($this->credentials instanceof StateInterface) {
|
||||
$config['state'] = $this->credentials->getState();
|
||||
}
|
||||
|
||||
if ($this->credentials instanceof ClientCredentialsGrantInterface) {
|
||||
return $config;
|
||||
}
|
||||
|
||||
$config['username'] = $this->credentials->getUsername();
|
||||
$config['password'] = $this->credentials->getPassword();
|
||||
|
||||
return $config;
|
||||
}
|
||||
|
||||
private function getGrantType(array $config): GrantTypeInterface
|
||||
{
|
||||
if ($this->credentials instanceof ClientCredentialsGrantInterface) {
|
||||
return new ClientCredentials($this->getReAuthClient(), $config);
|
||||
}
|
||||
|
||||
return new PasswordCredentials($this->getReAuthClient(), $config);
|
||||
}
|
||||
|
||||
private function configureMiddleware(OAuth2Middleware $oauth): void
|
||||
{
|
||||
if (!$this->config) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($this->config instanceof ConfigCredentialsSignerInterface) {
|
||||
$oauth->setClientCredentialsSigner($this->config->getCredentialsSigner());
|
||||
}
|
||||
|
||||
if ($this->config instanceof ConfigTokenPersistenceInterface) {
|
||||
$oauth->setTokenPersistence($this->config->getTokenPersistence());
|
||||
}
|
||||
|
||||
if ($this->config instanceof ConfigTokenSignerInterface) {
|
||||
$oauth->setAccessTokenSigner($this->config->getTokenSigner());
|
||||
}
|
||||
|
||||
if ($this->config instanceof ConfigTokenFactoryInterface) {
|
||||
$oauth->setTokenFactory($this->config->getTokenFactory());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Mautic\IntegrationsBundle\Auth\Support\Oauth2\ConfigAccess;
|
||||
|
||||
use kamermans\OAuth2\Signer\ClientCredentials\SignerInterface;
|
||||
use Mautic\IntegrationsBundle\Auth\Provider\AuthConfigInterface;
|
||||
|
||||
interface ConfigCredentialsSignerInterface extends AuthConfigInterface
|
||||
{
|
||||
public function getCredentialsSigner(): SignerInterface;
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Mautic\IntegrationsBundle\Auth\Support\Oauth2\ConfigAccess;
|
||||
|
||||
use Mautic\IntegrationsBundle\Auth\Provider\AuthConfigInterface;
|
||||
use Mautic\IntegrationsBundle\Auth\Support\Oauth2\Token\TokenFactoryInterface;
|
||||
|
||||
interface ConfigTokenFactoryInterface extends AuthConfigInterface
|
||||
{
|
||||
public function getTokenFactory(): TokenFactoryInterface;
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Mautic\IntegrationsBundle\Auth\Support\Oauth2\ConfigAccess;
|
||||
|
||||
use kamermans\OAuth2\Persistence\TokenPersistenceInterface as KamermansTokenPersistenceInterface;
|
||||
use Mautic\IntegrationsBundle\Auth\Provider\AuthConfigInterface;
|
||||
|
||||
interface ConfigTokenPersistenceInterface extends AuthConfigInterface
|
||||
{
|
||||
public function getTokenPersistence(): KamermansTokenPersistenceInterface;
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Mautic\IntegrationsBundle\Auth\Support\Oauth2\ConfigAccess;
|
||||
|
||||
use kamermans\OAuth2\Signer\AccessToken\SignerInterface;
|
||||
use Mautic\IntegrationsBundle\Auth\Provider\AuthConfigInterface;
|
||||
|
||||
interface ConfigTokenSignerInterface extends AuthConfigInterface
|
||||
{
|
||||
public function getTokenSigner(): SignerInterface;
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Mautic\IntegrationsBundle\Auth\Support\Oauth2\Token;
|
||||
|
||||
use kamermans\OAuth2\Token\TokenInterface;
|
||||
use kamermans\OAuth2\Token\TokenSerializer;
|
||||
|
||||
class IntegrationToken implements TokenInterface
|
||||
{
|
||||
// Pull in serialize() and unserialize() methods
|
||||
use TokenSerializer;
|
||||
|
||||
/**
|
||||
* @param mixed[] $extraData
|
||||
*/
|
||||
public function __construct(
|
||||
?string $accessToken,
|
||||
?string $refreshToken,
|
||||
$expiresAt = null,
|
||||
private array $extraData = [],
|
||||
) {
|
||||
$this->accessToken = (string) $accessToken;
|
||||
$this->refreshToken = (string) $refreshToken;
|
||||
$this->expiresAt = (int) $expiresAt;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string The access token
|
||||
*/
|
||||
public function getAccessToken(): string
|
||||
{
|
||||
return $this->accessToken;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string The refresh token
|
||||
*/
|
||||
public function getRefreshToken(): string
|
||||
{
|
||||
return $this->refreshToken;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int The expiration timestamp
|
||||
*/
|
||||
public function getExpiresAt(): int
|
||||
{
|
||||
return $this->expiresAt;
|
||||
}
|
||||
|
||||
public function isExpired(): bool
|
||||
{
|
||||
// Consider expired if there is not an access token
|
||||
if (!$this->getAccessToken()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Otherwise, consider expired if the expiration time has passed
|
||||
return $this->expiresAt && $this->expiresAt < time();
|
||||
}
|
||||
|
||||
public function getExtraData(): array
|
||||
{
|
||||
return $this->extraData;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Mautic\IntegrationsBundle\Auth\Support\Oauth2\Token;
|
||||
|
||||
use kamermans\OAuth2\Token\TokenInterface;
|
||||
|
||||
class IntegrationTokenFactory implements TokenFactoryInterface
|
||||
{
|
||||
/**
|
||||
* @param mixed[] $extraKeysToStore Extra keys returned by the service during the token process that needs to be captured
|
||||
* @param int|null $defaultExpiresIn Default time in seconds that tokens are good for if not given in the response
|
||||
*/
|
||||
public function __construct(
|
||||
private array $extraKeysToStore = [],
|
||||
private ?int $defaultExpiresIn = null,
|
||||
) {
|
||||
}
|
||||
|
||||
public function __invoke(array $data, ?TokenInterface $previousToken = null): IntegrationToken
|
||||
{
|
||||
$accessToken = null;
|
||||
$refreshToken = null;
|
||||
|
||||
// Read "access_token" attribute
|
||||
if (isset($data['access_token'])) {
|
||||
$accessToken = $data['access_token'];
|
||||
}
|
||||
|
||||
// Read "refresh_token" attribute
|
||||
if (isset($data['refresh_token'])) {
|
||||
$refreshToken = $data['refresh_token'];
|
||||
} elseif (null !== $previousToken) {
|
||||
// When requesting a new access token with a refresh token, the
|
||||
// server may not resend a new refresh token. In that case we
|
||||
// should keep the previous refresh token as valid.
|
||||
//
|
||||
// See http://tools.ietf.org/html/rfc6749#section-6
|
||||
$refreshToken = $previousToken->getRefreshToken();
|
||||
}
|
||||
|
||||
$expiresAt = $this->getExpiration($data);
|
||||
|
||||
return new IntegrationToken($accessToken, $refreshToken, $expiresAt, $this->getExtraData($data));
|
||||
}
|
||||
|
||||
private function getExtraData(array $data): array
|
||||
{
|
||||
$extraData = [];
|
||||
foreach ($this->extraKeysToStore as $key) {
|
||||
$extraData[$key] = $data[$key] ?? null;
|
||||
}
|
||||
|
||||
return $extraData;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed[] $data
|
||||
*/
|
||||
private function getExpiration(array $data): ?int
|
||||
{
|
||||
// Read the "expires_at" attribute
|
||||
if (isset($data['expires_at'])) {
|
||||
return (int) $data['expires_at'];
|
||||
}
|
||||
|
||||
// Read the "expires_in" attribute
|
||||
if (isset($data['expires_in'])) {
|
||||
return time() + (int) $data['expires_in'];
|
||||
}
|
||||
|
||||
// Facebook unfortunately breaks the spec by using 'expires' instead of 'expires_in'
|
||||
if (isset($data['expires'])) {
|
||||
return time() + (int) $data['expires'];
|
||||
}
|
||||
|
||||
// Fallback to the default if set
|
||||
if ($this->defaultExpiresIn) {
|
||||
return time() + $this->defaultExpiresIn;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Mautic\IntegrationsBundle\Auth\Support\Oauth2\Token;
|
||||
|
||||
use kamermans\OAuth2\Token\TokenInterface;
|
||||
|
||||
interface TokenFactoryInterface
|
||||
{
|
||||
public function __invoke(array $data, ?TokenInterface $previousToken = null): IntegrationToken;
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Mautic\IntegrationsBundle\Auth\Support\Oauth2\Token;
|
||||
|
||||
use kamermans\OAuth2\Persistence\TokenPersistenceInterface;
|
||||
use kamermans\OAuth2\Token\TokenInterface;
|
||||
use Mautic\IntegrationsBundle\Exception\IntegrationNotSetException;
|
||||
use Mautic\IntegrationsBundle\Helper\IntegrationsHelper;
|
||||
use Mautic\PluginBundle\Entity\Integration;
|
||||
|
||||
class TokenPersistence implements TokenPersistenceInterface
|
||||
{
|
||||
private ?Integration $integration = null;
|
||||
|
||||
public function __construct(
|
||||
private IntegrationsHelper $integrationsHelper,
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Restore the token data into the give token.
|
||||
*
|
||||
* @return TokenInterface|IntegrationToken Restored token
|
||||
*/
|
||||
public function restoreToken(TokenInterface $token): TokenInterface
|
||||
{
|
||||
$apiKeys = $this->getIntegration()->getApiKeys();
|
||||
$apiKeys['expires_at'] ??= null;
|
||||
|
||||
return new IntegrationToken(
|
||||
empty($apiKeys['access_token']) ? null : $apiKeys['access_token'],
|
||||
empty($apiKeys['refresh_token']) ? null : $apiKeys['refresh_token'],
|
||||
$apiKeys['expires_at'] ?? null
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Save the token data.
|
||||
*/
|
||||
public function saveToken(TokenInterface $token): void
|
||||
{
|
||||
$integration = $this->getIntegration();
|
||||
$oldApiKeys = $integration->getApiKeys();
|
||||
|
||||
if (null === $oldApiKeys) {
|
||||
$oldApiKeys = [];
|
||||
}
|
||||
|
||||
$newApiKeys = [
|
||||
'access_token' => $token->getAccessToken(),
|
||||
'refresh_token' => $token->getRefreshToken(),
|
||||
'expires_at' => $token->getExpiresAt(),
|
||||
];
|
||||
|
||||
$extraData = $token instanceof IntegrationToken ? $token->getExtraData() : [];
|
||||
$newApiKeys = array_merge($oldApiKeys, $extraData, $newApiKeys);
|
||||
|
||||
$integration->setApiKeys($newApiKeys);
|
||||
$this->integrationsHelper->saveIntegrationConfiguration($integration);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the saved token data.
|
||||
*/
|
||||
public function deleteToken(): void
|
||||
{
|
||||
$integration = $this->getIntegration();
|
||||
|
||||
$apiKeys = $integration->getApiKeys();
|
||||
|
||||
// Must delete both the access token and the expiration in order for the middleware to refresh
|
||||
unset($apiKeys['access_token'], $apiKeys['expires_at']);
|
||||
|
||||
$integration->setApiKeys($apiKeys);
|
||||
|
||||
$this->integrationsHelper->saveIntegrationConfiguration($integration);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if a token exists (although it may not be valid).
|
||||
*/
|
||||
public function hasToken(): bool
|
||||
{
|
||||
return !empty($this->getIntegration()->getApiKeys()['access_token']);
|
||||
}
|
||||
|
||||
public function setIntegration(Integration $integration): void
|
||||
{
|
||||
$this->integration = $integration;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws IntegrationNotSetException
|
||||
*/
|
||||
private function getIntegration(): Integration
|
||||
{
|
||||
if ($this->integration) {
|
||||
return $this->integration;
|
||||
}
|
||||
|
||||
throw new IntegrationNotSetException('Integration not set');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Mautic\IntegrationsBundle\Auth\Support\Oauth2\Token;
|
||||
|
||||
use kamermans\OAuth2\Token\RawToken;
|
||||
use Mautic\IntegrationsBundle\Helper\IntegrationsHelper;
|
||||
use Mautic\PluginBundle\Entity\Integration;
|
||||
|
||||
class TokenPersistenceFactory
|
||||
{
|
||||
public function __construct(
|
||||
private IntegrationsHelper $integrationsHelper,
|
||||
) {
|
||||
}
|
||||
|
||||
public function create(Integration $integration): TokenPersistence
|
||||
{
|
||||
$tokenPersistence = new TokenPersistence($this->integrationsHelper);
|
||||
|
||||
$tokenPersistence->setIntegration($integration);
|
||||
|
||||
$apiKeys = $integration->getApiKeys();
|
||||
|
||||
$token = new RawToken(
|
||||
$apiKeys['access_token'] ?? null,
|
||||
$apiKeys['refresh_token'] ?? null,
|
||||
$apiKeys['expires_at'] ?? null
|
||||
);
|
||||
|
||||
$tokenPersistence->restoreToken($token);
|
||||
|
||||
return $tokenPersistence;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user