Skip to content
Snippets Groups Projects
Commit 89ea3656 authored by David Basham's avatar David Basham Committed by Shawn Duncan
Browse files

Issue #3255621 by zerbash, FatherShawn: Generate access token, if Refresh token not exist

parent f7479afb
No related branches found
No related tags found
No related merge requests found
...@@ -67,7 +67,7 @@ class Oauth2Client extends Plugin { ...@@ -67,7 +67,7 @@ class Oauth2Client extends Plugin {
/** /**
* The set of scopes for the provider to use by default. * The set of scopes for the provider to use by default.
* *
* OPTIONAL * OPTIONAL.
* *
* @var string[]|null * @var string[]|null
*/ */
...@@ -76,7 +76,7 @@ class Oauth2Client extends Plugin { ...@@ -76,7 +76,7 @@ class Oauth2Client extends Plugin {
/** /**
* The separator used to join the scopes in the OAuth2 query string. * The separator used to join the scopes in the OAuth2 query string.
* *
* OPTIONAL * OPTIONAL.
* *
* @var string * @var string
*/ */
...@@ -85,7 +85,7 @@ class Oauth2Client extends Plugin { ...@@ -85,7 +85,7 @@ class Oauth2Client extends Plugin {
/** /**
* A flag that may be used by Oauth2ClientPluginInterface::storeAccessToken. * A flag that may be used by Oauth2ClientPluginInterface::storeAccessToken.
* *
* OPTIONAL * OPTIONAL.
* *
* Implementations may conditionally display a message on successful storage. * Implementations may conditionally display a message on successful storage.
* *
...@@ -96,7 +96,7 @@ class Oauth2Client extends Plugin { ...@@ -96,7 +96,7 @@ class Oauth2Client extends Plugin {
/** /**
* An associative array of classes that are composed into the provider. * An associative array of classes that are composed into the provider.
* *
* OPTIONAL * OPTIONAL.
* *
* Allowed keys are: * Allowed keys are:
* - grantFactory * - grantFactory
...@@ -104,13 +104,13 @@ class Oauth2Client extends Plugin { ...@@ -104,13 +104,13 @@ class Oauth2Client extends Plugin {
* - httpClient * - httpClient
* - optionProvider * - optionProvider
* *
* @var string[]|null
*
* @see \League\OAuth2\Client\Provider\AbstractProvider::__construct * @see \League\OAuth2\Client\Provider\AbstractProvider::__construct
* @see \League\OAuth2\Client\Provider\AbstractProvider::setGrantFactory * @see \League\OAuth2\Client\Provider\AbstractProvider::setGrantFactory
* @see \League\OAuth2\Client\Provider\AbstractProvider::setRequestFactory * @see \League\OAuth2\Client\Provider\AbstractProvider::setRequestFactory
* @see \League\OAuth2\Client\Provider\AbstractProvider::setHttpClient * @see \League\OAuth2\Client\Provider\AbstractProvider::setHttpClient
* @see \League\OAuth2\Client\Provider\AbstractProvider::setOptionProvider * @see \League\OAuth2\Client\Provider\AbstractProvider::setOptionProvider
*
* @var string[]|null
*/ */
public $collaborators; public $collaborators;
......
<?php
namespace Drupal\oauth2_client\Exception;
/**
* Allows implementing code to catch and renew with user interaction.
*/
class NonrenewableTokenException extends \Exception {
/**
* Construct the exception with a default message.
*
* @param string $grantType
* The grant type.
* @param string $message
* The Exception message to throw.
* @param int $code
* The Exception code.
* @param \Throwable $previous
* The previous exception used for the exception chaining.
*/
public function __construct(string $grantType = '', string $message = "", int $code = 0, \Throwable $previous = NULL) {
if (!empty($message) && !empty($grantType)) {
$message = "A token obtained using the $grantType grant has expired without a refresh, and cannot be renewed without user interaction";
}
parent::__construct($message, $code, $previous);
}
}
...@@ -5,6 +5,9 @@ namespace Drupal\oauth2_client\OAuth2\Client\OptionProvider; ...@@ -5,6 +5,9 @@ namespace Drupal\oauth2_client\OAuth2\Client\OptionProvider;
use Drupal\oauth2_client\Plugin\Oauth2Client\Oauth2ClientPluginInterface; use Drupal\oauth2_client\Plugin\Oauth2Client\Oauth2ClientPluginInterface;
use League\OAuth2\Client\OptionProvider\PostAuthOptionProvider; use League\OAuth2\Client\OptionProvider\PostAuthOptionProvider;
/**
* An option provider which extracts scope from the client plugin.
*/
class ClientCredentialsOptionProvider extends PostAuthOptionProvider { class ClientCredentialsOptionProvider extends PostAuthOptionProvider {
/** /**
...@@ -14,6 +17,9 @@ class ClientCredentialsOptionProvider extends PostAuthOptionProvider { ...@@ -14,6 +17,9 @@ class ClientCredentialsOptionProvider extends PostAuthOptionProvider {
*/ */
private $scopeOption; private $scopeOption;
/**
* {@inheritdoc}
*/
public function __construct(Oauth2ClientPluginInterface $clientPlugin) { public function __construct(Oauth2ClientPluginInterface $clientPlugin) {
$scopes = $clientPlugin->getScopes(); $scopes = $clientPlugin->getScopes();
if (!empty($scopes)) { if (!empty($scopes)) {
...@@ -21,9 +27,8 @@ class ClientCredentialsOptionProvider extends PostAuthOptionProvider { ...@@ -21,9 +27,8 @@ class ClientCredentialsOptionProvider extends PostAuthOptionProvider {
} }
} }
/** /**
* @inheritDoc * {@inheritdoc}
*/ */
public function getAccessTokenOptions($method, array $params) { public function getAccessTokenOptions($method, array $params) {
if (!empty($this->scopeOption)) { if (!empty($this->scopeOption)) {
......
...@@ -14,10 +14,10 @@ use Drupal\Core\Url; ...@@ -14,10 +14,10 @@ use Drupal\Core\Url;
use Drupal\oauth2_client\Service\CredentialProvider; use Drupal\oauth2_client\Service\CredentialProvider;
use Drupal\oauth2_client\Exception\Oauth2ClientPluginMissingKeyException; use Drupal\oauth2_client\Exception\Oauth2ClientPluginMissingKeyException;
use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\ContainerInterface;
use League\OAuth2\Client\Grant\GrantFactory; use League\OAuth2\Client\Grant\GrantFactory;
use League\OAuth2\Client\Tool\RequestFactory; use League\OAuth2\Client\Tool\RequestFactory;
use GuzzleHttp\ClientInterface; use GuzzleHttp\ClientInterface;
use League\OAuth2\Client\OptionProvider\OptionProviderInterface; use League\OAuth2\Client\OptionProvider\OptionProviderInterface;
/** /**
* Base class for Oauth2Client plugins. * Base class for Oauth2Client plugins.
...@@ -71,9 +71,9 @@ abstract class Oauth2ClientPluginBase extends PluginBase implements Oauth2Client ...@@ -71,9 +71,9 @@ abstract class Oauth2ClientPluginBase extends PluginBase implements Oauth2Client
/** /**
* A set of instantiated collaborator objects. * A set of instantiated collaborator objects.
* *
* OPTIONAL * OPTIONAL.
* *
* @var array{ * @var array {
* grantFactory?: \League\OAuth2\Client\Grant\GrantFactory, * grantFactory?: \League\OAuth2\Client\Grant\GrantFactory,
* requestFactory?: \League\OAuth2\Client\Tool\RequestFactory, * requestFactory?: \League\OAuth2\Client\Tool\RequestFactory,
* httpClient?: \GuzzleHttp\ClientInterface, * httpClient?: \GuzzleHttp\ClientInterface,
...@@ -411,7 +411,7 @@ abstract class Oauth2ClientPluginBase extends PluginBase implements Oauth2Client ...@@ -411,7 +411,7 @@ abstract class Oauth2ClientPluginBase extends PluginBase implements Oauth2Client
foreach ($collaborators as $type => $collaborator) { foreach ($collaborators as $type => $collaborator) {
$collaboratorObjects[$type] = new $collaborator(); $collaboratorObjects[$type] = new $collaborator();
} }
// Verify // Verify:
if (isset($collaboratorObjects['grantFactory']) && !($collaboratorObjects['grantFactory'] instanceof GrantFactory)) { if (isset($collaboratorObjects['grantFactory']) && !($collaboratorObjects['grantFactory'] instanceof GrantFactory)) {
throw new \TypeError('Collaborator key "grantFactory" must be of type GrantFactory'); throw new \TypeError('Collaborator key "grantFactory" must be of type GrantFactory');
} }
...@@ -429,7 +429,6 @@ abstract class Oauth2ClientPluginBase extends PluginBase implements Oauth2Client ...@@ -429,7 +429,6 @@ abstract class Oauth2ClientPluginBase extends PluginBase implements Oauth2Client
return $this->collaborators; return $this->collaborators;
} }
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
namespace Drupal\oauth2_client\Service; namespace Drupal\oauth2_client\Service;
use Drupal\Core\State\StateInterface; use Drupal\Core\State\StateInterface;
use Drupal\oauth2_client\Exception\NonrenewableTokenException;
use Drupal\oauth2_client\PluginManager\Oauth2ClientPluginManagerInterface; use Drupal\oauth2_client\PluginManager\Oauth2ClientPluginManagerInterface;
use Drupal\oauth2_client\Service\Grant\Oauth2ClientGrantServiceInterface; use Drupal\oauth2_client\Service\Grant\Oauth2ClientGrantServiceInterface;
use Drupal\oauth2_client\Service\Grant\ResourceOwnersCredentialsGrantService; use Drupal\oauth2_client\Service\Grant\ResourceOwnersCredentialsGrantService;
...@@ -78,34 +79,43 @@ class Oauth2ClientService extends Oauth2ClientServiceBase { ...@@ -78,34 +79,43 @@ class Oauth2ClientService extends Oauth2ClientServiceBase {
* Thrown in the upstream League library. * Thrown in the upstream League library.
*/ */
public function getAccessToken($pluginId, $username = '', $password = '') { public function getAccessToken($pluginId, $username = '', $password = '') {
$client = $this->getClient($pluginId);
$grant_type = $client->getGrantType();
$accessToken = $this->retrieveAccessToken($pluginId); $accessToken = $this->retrieveAccessToken($pluginId);
if ($accessToken instanceof AccessTokenInterface) { if ($accessToken instanceof AccessTokenInterface) {
$refreshToken = $accessToken->getRefreshToken();
$expirationTimestamp = $accessToken->getExpires(); $expirationTimestamp = $accessToken->getExpires();
if (!empty($expirationTimestamp) && $accessToken->hasExpired() && !empty($refreshToken)) { $expired = !empty($expirationTimestamp) && $accessToken->hasExpired();
$this->grantServices['refresh_token']->getAccessToken($pluginId); if (!$expired) {
$accessToken = $this->retrieveAccessToken($pluginId); return $accessToken;
}
$refreshToken = $accessToken->getRefreshToken();
if (!empty($refreshToken)) {
$accessToken = $this->grantServices['refresh_token']->getAccessToken($pluginId);
return $accessToken;
}
if ($grant_type == 'authorization_code') {
throw new NonrenewableTokenException($grant_type);
}
if ($grant_type == 'resource_owner') {
throw new NonrenewableTokenException('resource_owner');
} }
} }
else {
$client = $this->getClient($pluginId);
switch ($client->getGrantType()) { switch ($grant_type) {
case 'authorization_code': case 'authorization_code':
$this->grantServices['authorization_code']->getAccessToken($pluginId); $this->grantServices['authorization_code']->getAccessToken($pluginId);
break; break;
case 'client_credentials': case 'client_credentials':
$this->grantServices['client_credentials']->getAccessToken($pluginId); $this->grantServices['client_credentials']->getAccessToken($pluginId);
$accessToken = $this->retrieveAccessToken($pluginId); $accessToken = $this->retrieveAccessToken($pluginId);
break; break;
case 'resource_owner': case 'resource_owner':
$this->grantServices['resource_owner']->setUsernamePassword($pluginId, $username, $password); $this->grantServices['resource_owner']->setUsernamePassword($pluginId, $username, $password);
$this->grantServices['resource_owner']->getAccessToken($pluginId); $this->grantServices['resource_owner']->getAccessToken($pluginId);
$accessToken = $this->retrieveAccessToken($pluginId); $accessToken = $this->retrieveAccessToken($pluginId);
break; break;
}
} }
return $accessToken; return $accessToken;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment