Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • project/simple_oauth
  • issue/simple_oauth-3021054
  • issue/simple_oauth-3186649
  • issue/simple_oauth-3185673
  • issue/simple_oauth-2978041
  • issue/simple_oauth-3189147
  • issue/simple_oauth-3192392
  • issue/simple_oauth-3193609
  • issue/simple_oauth-3026121
  • issue/simple_oauth-3116782
  • issue/simple_oauth-3194635
  • issue/simple_oauth-3182418
  • issue/simple_oauth-3049449
  • issue/simple_oauth-3225751
  • issue/simple_oauth-2978831
  • issue/simple_oauth-3126716
  • issue/simple_oauth-3283821
  • issue/simple_oauth-3241249
  • issue/simple_oauth-3252185
  • issue/simple_oauth-3173947
  • issue/simple_oauth-3230707
  • issue/simple_oauth-3167287
  • issue/simple_oauth-3257003
  • issue/simple_oauth-3089447
  • issue/simple_oauth-3261883
  • issue/simple_oauth-3258402
  • issue/simple_oauth-3267049
  • issue/simple_oauth-3263590
  • issue/simple_oauth-3186652
  • issue/simple_oauth-3263611
  • issue/simple_oauth-3095250
  • issue/simple_oauth-3273131
  • issue/simple_oauth-3091689
  • issue/simple_oauth-3263631
  • issue/simple_oauth-3277083
  • issue/simple_oauth-3263651
  • issue/simple_oauth-3284629
  • issue/simple_oauth-3269822
  • issue/simple_oauth-3287927
  • issue/simple_oauth-3290904
  • issue/simple_oauth-2971579
  • issue/simple_oauth-3260992
  • issue/simple_oauth-3292079
  • issue/simple_oauth-3276214
  • issue/simple_oauth-3295744
  • issue/simple_oauth-3133698
  • issue/simple_oauth-3304685
  • issue/simple_oauth-2946882
  • issue/simple_oauth-3132865
  • issue/simple_oauth-3300632
  • issue/simple_oauth-3289642
  • issue/simple_oauth-3304983
  • issue/simple_oauth-3131666
  • issue/simple_oauth-2857930
  • issue/simple_oauth-3298067
  • issue/simple_oauth-3317444
  • issue/simple_oauth-3173085
  • issue/simple_oauth-3315448
  • issue/simple_oauth-3257293
  • issue/simple_oauth-3174705
  • issue/simple_oauth-3326143
  • issue/simple_oauth-3320581
  • issue/simple_oauth-3319134
  • issue/simple_oauth-3321070
  • issue/simple_oauth-3082984
  • issue/simple_oauth-3322325
  • issue/simple_oauth-3323009
  • issue/simple_oauth-3323412
  • issue/simple_oauth-3324934
  • issue/simple_oauth-3324946
  • issue/simple_oauth-3330290
  • issue/simple_oauth-3330295
  • issue/simple_oauth-3330328
  • issue/simple_oauth-3330360
  • issue/simple_oauth-3331436
  • issue/simple_oauth-3330963
  • issue/simple_oauth-3331722
  • issue/simple_oauth-3345687
  • issue/simple_oauth-3348363
  • issue/simple_oauth-3345597
  • issue/simple_oauth-3352607
  • issue/simple_oauth-3353859
  • issue/simple_oauth-3321690
  • issue/simple_oauth-3402191
  • issue/simple_oauth-3402385
  • issue/simple_oauth-3371228
  • issue/simple_oauth-3374084
  • issue/simple_oauth-3375069
  • issue/simple_oauth-3380716
  • issue/simple_oauth-3364376
  • issue/simple_oauth-3033472
  • issue/simple_oauth-3391076
  • issue/simple_oauth-3393983
  • issue/simple_oauth-3396188
  • issue/simple_oauth-3397590
  • issue/simple_oauth-3398468
  • issue/simple_oauth-3398476
  • issue/simple_oauth-3398745
  • issue/simple_oauth-3399091
  • issue/simple_oauth-3154617
  • issue/simple_oauth-3412622
  • issue/simple_oauth-3425975
  • issue/simple_oauth-3426075
  • issue/simple_oauth-3424378
  • issue/simple_oauth-3428014
  • issue/simple_oauth-3439309
  • issue/simple_oauth-3444193
  • issue/simple_oauth-3432313
  • issue/simple_oauth-3436728
  • issue/simple_oauth-3095332
  • issue/simple_oauth-3383342
  • issue/simple_oauth-3451692
  • issue/simple_oauth-3452470
  • issue/simple_oauth-3453938
  • issue/simple_oauth-3455605
  • issue/simple_oauth-3454416
  • issue/simple_oauth-3456043
  • issue/simple_oauth-3457334
  • issue/simple_oauth-3460689
  • issue/simple_oauth-3470777
  • issue/simple_oauth-3475277
  • issue/simple_oauth-3475537
  • issue/simple_oauth-3477768
  • issue/simple_oauth-3470719
  • issue/simple_oauth-3479129
  • issue/simple_oauth-3459456
  • issue/simple_oauth-3480844
  • issue/simple_oauth-3454338
  • issue/simple_oauth-3495678
  • issue/simple_oauth-3277256
  • issue/simple_oauth-3483483
  • issue/simple_oauth-3404804
  • issue/simple_oauth-3104334
  • issue/simple_oauth-3426090
  • issue/simple_oauth-3416419
  • issue/simple_oauth-3494954
  • issue/simple_oauth-3495325
  • issue/simple_oauth-3496752
  • issue/simple_oauth-3496757
  • issue/simple_oauth-3498190
  • issue/simple_oauth-3502576
  • issue/simple_oauth-3502582
  • issue/simple_oauth-3502661
  • issue/simple_oauth-3503108
  • issue/simple_oauth-3503340
  • issue/simple_oauth-3507450
  • issue/simple_oauth-3507767
  • issue/simple_oauth-3508777
  • issue/simple_oauth-3509299
  • issue/simple_oauth-3512143
150 results
Show changes
Commits on Source (12)
Showing
with 193 additions and 152 deletions
variables:
PHP_TAG: "8.1"
include:
- project: 'drupalspoons/composer-plugin'
# Best practice is to pin to a tag or a SHA1. https://docs.gitlab.com/ee/ci/yaml/#includefile
ref: '2.1.0'
file: 'templates/.gitlab-ci.yml'
composer_node:
stage: build
variables:
DRUPAL_CORE_CONSTRAINT: ^9.3
remote: 'https://gitlab.com/drupalspoons/composer-plugin/-/raw/master/templates/.gitlab-ci.yml'
language: php
sudo: false
php:
- 5.6
- 7
env:
- DRUPAL_CORE=8.2.x
- DRUPAL_CORE=8.3.x
matrix:
fast_finish: true
mysql:
database: drupal
username: root
encoding: utf8
# Cache composer downloads because cloning Coder form drupal.org is very slow :-(
cache:
directories:
- $HOME/.composer
before_script:
# Remove Xdebug as we don't need it and it causes
# PHP Fatal error: Maximum function nesting level of '256' reached.
# We also don't care if that file exists or not on PHP 7.
- phpenv config-rm xdebug.ini || true
# Remember the current simple_oauth test directory for later use in the Drupal
# installation.
- TESTDIR=$(pwd)
# Navigate out of module directory to prevent blown stack by recursive module
# lookup.
- cd ..
# Create database.
- mysql -e 'create database drupal'
# Export database variable for kernel tests.
- export SIMPLETEST_DB=mysql://root:@127.0.0.1/drupal
- travis_retry git clone --branch $DRUPAL_CORE --depth 1 http://git.drupal.org/project/drupal.git
- cd drupal
# Reference simple_oauth in build site.
- ln -s $TESTDIR modules/simple_oauth
- travis_retry composer self-update
- travis_retry composer install
# Add dependency manually since installing via git pull is not bringing that.
- travis_retry composer require league/oauth2-server:^5.1
# Start a web server on port 8888, run in the background.
- php -S localhost:8888 &
# Export web server URL for browser tests.
- export SIMPLETEST_BASE_URL=http://localhost:8888
# Install PHPCS to check for Drupal coding standards.
- travis_retry composer global require drupal/coder
- ~/.composer/vendor/bin/phpcs --config-set installed_paths ~/.composer/vendor/drupal/coder/coder_sniffer
script:
# Run the PHPUnit tests which also include the kernel tests.
- ./vendor/bin/phpunit --verbose --color -c ./core/phpunit.xml.dist ./modules/simple_oauth
# Check for coding standards violations
- cd modules/simple_oauth && ~/.composer/vendor/bin/phpcs --standard=DrupalPractice .
......@@ -6,13 +6,13 @@
"lcobucci/jwt": "^4",
"league/oauth2-server": "^8.3",
"steverhoades/oauth2-openid-connect-server": "^2.4",
"drupal/consumers": "^1.2",
"drupal/consumers": "^1.14",
"php": ">=7.4"
},
"require-dev": {
"phpspec/prophecy-phpunit": "^2"
},
"license": "GPL-2.0+",
"license": "GPL-2.0-or-later",
"authors": [
{
"name": "Mateu Aguiló Bosch",
......
<?xml version="1.0" encoding="UTF-8"?>
<phpunit>
<listeners>
<listener class="\Drupal\Tests\Listeners\DrupalListener">
</listener>
</listeners>
</phpunit>
......@@ -8,6 +8,7 @@
use Drupal\Core\Config\FileStorage;
use Drupal\Core\Field\BaseFieldDefinition;
use Drupal\Core\StringTranslation\TranslatableMarkup;
use Drupal\simple_oauth\Entity\Oauth2TokenStorageSchema;
/**
* Define the default batch size.
......@@ -116,3 +117,25 @@ function simple_oauth_update_8501(&$sandbox) {
$config->set('disable_openid_connect', FALSE);
$config->save();
}
/**
* Add indexes to oauth2_token value field.
*/
function simple_oauth_update_8502() {
$entity_type_manager = \Drupal::entityTypeManager();
$definition_update_manager = \Drupal::entityDefinitionUpdateManager();
$entity_type = $entity_type_manager->getDefinition('oauth2_token')
->setHandlerClass('storage_schema', Oauth2TokenStorageSchema::class);
// Regenerate entity type indexes.
$definition_update_manager->updateEntityType($entity_type);
}
/**
* Resolve mismatched field definition for oauth2_token.
*/
function simple_oauth_update_8503() {
$definition_update_manager = \Drupal::entityDefinitionUpdateManager();
$field_storage_definition = $definition_update_manager->getFieldStorageDefinition('value', 'oauth2_token');
$definition_update_manager->updateFieldStorageDefinition($field_storage_definition);
}
......@@ -11,7 +11,7 @@ use Drupal\Core\Field\BaseFieldDefinition;
use Drupal\Core\Field\FieldStorageDefinitionInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Session\AccountInterface;
use Drupal\consumers\Entity\Consumer;
use Drupal\consumers\Entity\ConsumerInterface;
use Drupal\Core\StringTranslation\TranslatableMarkup;
use Drupal\Core\Url;
use Drupal\user\RoleInterface;
......@@ -45,7 +45,7 @@ function simple_oauth_entity_update(EntityInterface $entity) {
if ($entity instanceof AccountInterface) {
$collector->deleteMultipleTokens($collector->collectForAccount($entity));
}
if ($entity instanceof Consumer) {
if ($entity instanceof ConsumerInterface) {
$collector->deleteMultipleTokens($collector->collectForClient($entity));
}
}
......@@ -160,7 +160,9 @@ function simple_oauth_form_consumer_form_alter(array &$form, FormStateInterface
unset($form['roles']['widget']['#options'][RoleInterface::ANONYMOUS_ID]);
unset($form['roles']['widget']['#options'][RoleInterface::AUTHENTICATED_ID]);
// Get the admin role.
$admin_roles = $entity_type_manager->getStorage('user_role')->getQuery()
$admin_roles = $entity_type_manager->getStorage('user_role')
->getQuery()
->accessCheck()
->condition('is_admin', TRUE)
->execute();
$default_value = reset($admin_roles);
......@@ -198,7 +200,7 @@ function simple_oauth_form_consumer_form_alter(array &$form, FormStateInterface
* @param \Drupal\Core\Form\FormStateInterface $form_state
* The state.
*/
function simple_oauth_form_consumer_form_submit($entity_type_id, Consumer $entity, array &$form, FormStateInterface $form_state) {
function simple_oauth_form_consumer_form_submit($entity_type_id, ConsumerInterface $entity, array &$form, FormStateInterface $form_state) {
if ($entity_type_id !== 'consumer') {
return;
}
......
......@@ -4,6 +4,7 @@ namespace Drupal\simple_oauth\Authentication\Provider;
use Drupal\Core\Authentication\AuthenticationProviderInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\simple_oauth\Authentication\TokenAuthUser;
use Drupal\simple_oauth\PageCache\SimpleOauthRequestPolicyInterface;
use Drupal\simple_oauth\Server\ResourceServerInterface;
......@@ -16,6 +17,8 @@ use Symfony\Component\HttpKernel\Exception\HttpException;
*/
class SimpleOauthAuthenticationProvider implements AuthenticationProviderInterface {
use StringTranslationTrait;
/**
* @var \Drupal\simple_oauth\Server\ResourceServerInterface
*/
......@@ -97,7 +100,7 @@ class SimpleOauthAuthenticationProvider implements AuthenticationProviderInterfa
$token->revoke();
$token->save();
$exception = OAuthServerException::accessDenied(
t(
$this->t(
'%name is blocked or has not been activated yet.',
['%name' => $account->getAccountName()]
)
......@@ -115,7 +118,7 @@ class SimpleOauthAuthenticationProvider implements AuthenticationProviderInterfa
$request->files->add($auth_request->files->all());
// Set consumer ID header on successful authentication, so negotiators
// will trigger correctly.
$request->headers->set('X-Consumer-ID', $account->getConsumer()->uuid());
$request->headers->set('X-Consumer-ID', $account->getConsumer()->getClientId());
return $account;
}
......
......@@ -2,6 +2,7 @@
namespace Drupal\simple_oauth\Authentication;
use Drupal\consumers\Entity\ConsumerInterface;
use Drupal\Core\Entity\EntityStorageInterface;
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Session\AccountInterface;
......@@ -34,7 +35,7 @@ class TokenAuthUser implements TokenAuthUserInterface {
/**
* The activated consumer instance.
*
* @var \Drupal\consumers\Entity\Consumer
* @var \Drupal\consumers\Entity\ConsumerInterface
*/
protected $consumer;
......@@ -71,7 +72,7 @@ class TokenAuthUser implements TokenAuthUserInterface {
/**
* {@inheritdoc}
*/
public function getConsumer() {
public function getConsumer(): ConsumerInterface {
return $this->consumer;
}
......
......@@ -2,6 +2,7 @@
namespace Drupal\simple_oauth\Authentication;
use Drupal\consumers\Entity\ConsumerInterface;
use Drupal\user\UserInterface;
/**
......@@ -20,9 +21,9 @@ interface TokenAuthUserInterface extends \IteratorAggregate, UserInterface {
/**
* Get the activated consumer.
*
* @return \Drupal\consumers\Entity\Consumer
* @return \Drupal\consumers\Entity\ConsumerInterface
* The activated consumer after authentication.
*/
public function getConsumer();
public function getConsumer(): ConsumerInterface;
}
......@@ -15,6 +15,7 @@ use GuzzleHttp\Psr7\Response;
use League\OAuth2\Server\AuthorizationServer;
use League\OAuth2\Server\Entities\ScopeEntityInterface;
use League\OAuth2\Server\Exception\OAuthServerException;
use League\OAuth2\Server\Repositories\ClientRepositoryInterface;
use League\OAuth2\Server\RequestTypes\AuthorizationRequest;
use Symfony\Bridge\PsrHttpMessage\HttpMessageFactoryInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
......@@ -54,6 +55,11 @@ class Oauth2AuthorizeController extends ControllerBase {
*/
protected $knownClientRepository;
/**
* @var \League\OAuth2\Server\Repositories\ClientRepositoryInterface
*/
protected $clientRepository;
/**
* Oauth2AuthorizeController construct.
*
......@@ -65,17 +71,21 @@ class Oauth2AuthorizeController extends ControllerBase {
* The config factory.
* @param \Drupal\simple_oauth\KnownClientsRepositoryInterface $known_clients_repository
* The known client repository service.
* @param \League\OAuth2\Server\Repositories\ClientRepositoryInterface $client_repository
* The client repository service.
*/
public function __construct(
HttpMessageFactoryInterface $message_factory,
Oauth2GrantManagerInterface $grant_manager,
ConfigFactoryInterface $config_factory,
KnownClientsRepositoryInterface $known_clients_repository
KnownClientsRepositoryInterface $known_clients_repository,
ClientRepositoryInterface $client_repository
) {
$this->messageFactory = $message_factory;
$this->grantManager = $grant_manager;
$this->configFactory = $config_factory;
$this->knownClientRepository = $known_clients_repository;
$this->clientRepository = $client_repository;
}
/**
......@@ -86,7 +96,8 @@ class Oauth2AuthorizeController extends ControllerBase {
$container->get('psr7.http_message_factory'),
$container->get('plugin.manager.oauth2_grant.processor'),
$container->get('config.factory'),
$container->get('simple_oauth.known_clients')
$container->get('simple_oauth.known_clients'),
$container->get('simple_oauth.repositories.client')
);
}
......@@ -102,24 +113,21 @@ class Oauth2AuthorizeController extends ControllerBase {
* @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
*/
public function authorize(Request $request) {
$client_uuid = $request->get('client_id');
$client_id = $request->get('client_id');
$server_request = $this->messageFactory->createRequest($request);
if (empty($client_uuid)) {
if (empty($client_id)) {
return OAuthServerException::invalidClient($server_request)
->generateHttpResponse(new Response());
}
$consumer_storage = $this->entityTypeManager()->getStorage('consumer');
$client_drupal_entities = $consumer_storage
->loadByProperties([
'uuid' => $client_uuid,
]);
if (empty($client_drupal_entities)) {
$client_drupal_entity = $this->clientRepository
->getClientEntity($client_id);
if (empty($client_drupal_entity)) {
return OAuthServerException::invalidClient($server_request)
->generateHttpResponse(new Response());
}
$client_drupal_entity = reset($client_drupal_entities);
$is_third_party = $client_drupal_entity->get('third_party')->value;
$consumer_entity = $client_drupal_entity->getDrupalEntity();
$is_third_party = $consumer_entity->get('third_party')->value;
$scopes = [];
if ($request->query->get('scope')) {
......@@ -139,7 +147,7 @@ class Oauth2AuthorizeController extends ControllerBase {
// Client ID and secret may be passed as Basic Auth. Copy the headers.
return RedirectResponse::create($url->toString(), 302, $request->headers->all());
}
elseif (!$is_third_party || $this->isKnownClient($client_uuid, $scopes)) {
elseif (!$is_third_party || $this->isKnownClient($client_id, $scopes)) {
// Login user may skip the grant step if the client is not third party or
// known.
if ($request->get('response_type') == 'code') {
......@@ -152,7 +160,7 @@ class Oauth2AuthorizeController extends ControllerBase {
$grant_type = NULL;
}
try {
$server = $this->grantManager->getAuthorizationServer($grant_type, $client_drupal_entity);
$server = $this->grantManager->getAuthorizationServer($grant_type, $consumer_entity);
$ps7_request = $server_request;
$auth_request = $server->validateAuthorizationRequest($ps7_request);
}
......@@ -240,19 +248,19 @@ class Oauth2AuthorizeController extends ControllerBase {
/**
* Whether the client with the given scopes is known and already authorized.
*
* @param string $client_uuid
* The client UUID.
* @param string $client_id
* The client ID.
* @param string[] $scopes
* The list of scopes.
*
* @return bool
* TRUE if the client is authorized, FALSE otherwise.
*/
protected function isKnownClient($client_uuid, array $scopes) {
protected function isKnownClient($client_id, array $scopes) {
if (!$this->configFactory->get('simple_oauth.settings')->get('remember_clients')) {
return FALSE;
}
return $this->knownClientRepository->isAuthorized($this->currentUser()->id(), $client_uuid, $scopes);
return $this->knownClientRepository->isAuthorized($this->currentUser()->id(), $client_id, $scopes);
}
}
......@@ -10,6 +10,7 @@ use Drupal\Core\Form\FormStateInterface;
use Drupal\simple_oauth\KnownClientsRepositoryInterface;
use Drupal\simple_oauth\Plugin\Oauth2GrantManagerInterface;
use League\OAuth2\Server\Exception\OAuthServerException;
use League\OAuth2\Server\Repositories\ClientRepositoryInterface;
use Symfony\Bridge\PsrHttpMessage\HttpFoundationFactoryInterface;
use Symfony\Bridge\PsrHttpMessage\HttpMessageFactoryInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
......@@ -68,6 +69,12 @@ class Oauth2AuthorizeForm extends FormBase {
*/
protected $knownClientRepository;
/**
* @var \League\OAuth2\Server\Repositories\ClientRepositoryInterface
*/
protected $clientRepository;
/**
* Oauth2AuthorizeForm constructor.
*
......@@ -83,14 +90,17 @@ class Oauth2AuthorizeForm extends FormBase {
* The config factory.
* @param \Drupal\simple_oauth\KnownClientsRepositoryInterface $known_clients_repository
* The known client repository service.
* @param \League\OAuth2\Server\Repositories\ClientRepositoryInterface $client_repository
* The client repository service.
*/
public function __construct(EntityTypeManagerInterface $entity_type_manager, HttpMessageFactoryInterface $message_factory, HttpFoundationFactoryInterface $foundation_factory, Oauth2GrantManagerInterface $grant_manager, ConfigFactoryInterface $config_factory, KnownClientsRepositoryInterface $known_clients_repository) {
public function __construct(EntityTypeManagerInterface $entity_type_manager, HttpMessageFactoryInterface $message_factory, HttpFoundationFactoryInterface $foundation_factory, Oauth2GrantManagerInterface $grant_manager, ConfigFactoryInterface $config_factory, KnownClientsRepositoryInterface $known_clients_repository, ClientRepositoryInterface $client_repository) {
$this->entityTypeManager = $entity_type_manager;
$this->messageFactory = $message_factory;
$this->foundationFactory = $foundation_factory;
$this->grantManager = $grant_manager;
$this->configFactory = $config_factory;
$this->knownClientRepository = $known_clients_repository;
$this->clientRepository = $client_repository;
}
/**
......@@ -103,7 +113,8 @@ class Oauth2AuthorizeForm extends FormBase {
$container->get('psr7.http_foundation_factory'),
$container->get('plugin.manager.oauth2_grant.processor'),
$container->get('config.factory'),
$container->get('simple_oauth.known_clients')
$container->get('simple_oauth.known_clients'),
$container->get('simple_oauth.repositories.client')
);
}
......@@ -143,20 +154,17 @@ class Oauth2AuthorizeForm extends FormBase {
else {
$grant_type = NULL;
}
$client_uuid = $request->get('client_id');
$consumer_storage = $this->entityTypeManager->getStorage('consumer');
$client_drupal_entities = $consumer_storage
->loadByProperties([
'uuid' => $client_uuid,
]);
if (empty($client_drupal_entities)) {
$client_id = $request->get('client_id');
$client_drupal_entity = $this->clientRepository
->getClientEntity($client_id);
if (empty($client_drupal_entity)) {
$server_request = $this->messageFactory->createRequest($request);
throw OAuthServerException::invalidClient($server_request);
}
$client_drupal_entity = reset($client_drupal_entities);
$consumer_entity = $client_drupal_entity->getDrupalEntity();
$this->server = $this
->grantManager
->getAuthorizationServer($grant_type, $client_drupal_entity);
->getAuthorizationServer($grant_type, $consumer_entity);
// Transform the HTTP foundation request object into a PSR-7 object. The
// OAuth library expects a PSR-7 request.
......@@ -175,7 +183,7 @@ class Oauth2AuthorizeForm extends FormBase {
$cacheablity_metadata = new CacheableMetadata();
$form['client'] = $manager->getViewBuilder('consumer')->view($client_drupal_entity);
$form['client'] = $manager->getViewBuilder('consumer')->view($consumer_entity);
$form['scopes'] = [
'#title' => $this->t('Permissions'),
'#theme' => 'item_list',
......@@ -183,7 +191,7 @@ class Oauth2AuthorizeForm extends FormBase {
];
$client_roles = [];
foreach ($client_drupal_entity->get('roles') as $role_item) {
foreach ($consumer_entity->get('roles') as $role_item) {
$client_roles[$role_item->target_id] = $role_item->entity;
}
......@@ -207,7 +215,7 @@ class Oauth2AuthorizeForm extends FormBase {
'#type' => 'hidden',
'#value' => $request->get('redirect_uri') ?
$request->get('redirect_uri') :
$client_drupal_entity->get('redirect')->value,
$consumer_entity->get('redirect')->value,
];
$form['submit'] = [
'#type' => 'submit',
......
......@@ -7,6 +7,7 @@ use Drupal\simple_oauth\Plugin\Oauth2GrantManagerInterface;
use GuzzleHttp\Psr7\Response;
use League\OAuth2\Server\AuthorizationServer;
use League\OAuth2\Server\Exception\OAuthServerException;
use League\OAuth2\Server\Repositories\ClientRepositoryInterface;
use Psr\Http\Message\ServerRequestInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
......@@ -17,14 +18,22 @@ class Oauth2Token extends ControllerBase {
*/
protected $grantManager;
/**
* @var \League\OAuth2\Server\Repositories\ClientRepositoryInterface
*/
protected $clientRepository;
/**
* Oauth2Token constructor.
*
* @param \Drupal\simple_oauth\Plugin\Oauth2GrantManagerInterface $grant_manager
* The grant manager.
* @param \League\OAuth2\Server\Repositories\ClientRepositoryInterface $client_repository
* The client repository service.
*/
public function __construct(Oauth2GrantManagerInterface $grant_manager) {
public function __construct(Oauth2GrantManagerInterface $grant_manager, ClientRepositoryInterface $client_repository) {
$this->grantManager = $grant_manager;
$this->clientRepository = $client_repository;
}
/**
......@@ -32,7 +41,8 @@ class Oauth2Token extends ControllerBase {
*/
public static function create(ContainerInterface $container) {
return new static(
$container->get('plugin.manager.oauth2_grant.processor')
$container->get('plugin.manager.oauth2_grant.processor'),
$container->get('simple_oauth.repositories.client')
);
}
......@@ -43,23 +53,19 @@ class Oauth2Token extends ControllerBase {
// Extract the grant type from the request body.
$body = $request->getParsedBody();
$grant_type_id = !empty($body['grant_type']) ? $body['grant_type'] : 'implicit';
$client_drupal_entity = NULL;
$consumer_entity = NULL;
if (!empty($body['client_id'])) {
$consumer_storage = $this->entityTypeManager()->getStorage('consumer');
$client_drupal_entities = $consumer_storage
->loadByProperties([
'uuid' => $body['client_id'],
]);
if (empty($client_drupal_entities)) {
return OAuthServerException::invalidClient($request)
->generateHttpResponse(new Response());
$client_drupal_entity = $this->clientRepository
->getClientEntity($body['client_id']);
if (empty($client_drupal_entity)) {
return OAuthServerException::invalidClient($request)->generateHttpResponse(new Response());
}
$client_drupal_entity = reset($client_drupal_entities);
$consumer_entity = $client_drupal_entity->getDrupalEntity();
}
// Get the auth server object from that uses the League library.
try {
// Respond to the incoming request and fill in the response.
$auth_server = $this->grantManager->getAuthorizationServer($grant_type_id, $client_drupal_entity);
$auth_server = $this->grantManager->getAuthorizationServer($grant_type_id, $consumer_entity);
$response = $this->handleToken($request, $auth_server);
}
catch (OAuthServerException $exception) {
......
......@@ -2,7 +2,7 @@
namespace Drupal\simple_oauth\Entities;
use Drupal\consumers\Entity\Consumer;
use Drupal\consumers\Entity\ConsumerInterface;
use League\OAuth2\Server\Entities\Traits\ClientTrait;
use League\OAuth2\Server\Entities\Traits\EntityTrait;
......@@ -11,19 +11,21 @@ class ClientEntity implements ClientEntityInterface {
use EntityTrait, ClientTrait;
/**
* @var \Drupal\consumers\Entity\Consumer
* The consumer entity.
*
* @var \Drupal\consumers\Entity\ConsumerInterface
*/
protected $entity;
/**
* ClientEntity constructor.
*
* @param \Drupal\consumers\Entity\Consumer $entity
* @param \Drupal\consumers\Entity\ConsumerInterface $entity
* The Drupal entity.
*/
public function __construct(Consumer $entity) {
public function __construct(ConsumerInterface $entity) {
$this->entity = $entity;
$this->setIdentifier($entity->uuid());
$this->setIdentifier($entity->getClientId());
$this->setName($entity->label());
if ($entity->hasField('redirect')) {
$this->redirectUri = $entity->get('redirect')->value;
......
......@@ -17,7 +17,7 @@ interface ClientEntityInterface extends LeagueClientEntityInterface {
/**
* Returns the associated Drupal entity.
*
* @return \Drupal\consumers\Entity\Consumer
* @return \Drupal\consumers\Entity\ConsumerInterface
* The Drupal entity.
*/
public function getDrupalEntity();
......
......@@ -124,8 +124,8 @@ class Oauth2TokenSettingsForm extends ConfigFormBase {
];
$form['authorization_code_expiration'] = [
'#type' => 'number',
'#title' => t('Authorization code expiration time'),
'#description' => t('The default value, in seconds, to be used as expiration time when creating new authorization codes. If you are not sure about this value, use the same value as above for <em>Access token expiration time</em>.'),
'#title' => $this->t('Authorization code expiration time'),
'#description' => $this->t('The default value, in seconds, to be used as expiration time when creating new authorization codes. If you are not sure about this value, use the same value as above for <em>Access token expiration time</em>.'),
'#default_value' => \Drupal::config('simple_oauth.settings')
->get('authorization_code_expiration'),
'#weight' => 0,
......@@ -203,8 +203,8 @@ class Oauth2TokenSettingsForm extends ConfigFormBase {
}
$form['use_implicit'] = [
'#type' => 'checkbox',
'#title' => t('Enable the implicit grant?'),
'#description' => t('The implicit grant has the potential to be used in an insecure way. Only enable this if you understand the risks. See https://tools.ietf.org/html/rfc6819#section-4.4.2 for more information.'),
'#title' => $this->t('Enable the implicit grant?'),
'#description' => $this->t('The implicit grant has the potential to be used in an insecure way. Only enable this if you understand the risks. See https://tools.ietf.org/html/rfc6819#section-4.4.2 for more information.'),
'#default_value' => \Drupal::config('simple_oauth.settings')->get('use_implicit'),
];
......
......@@ -19,6 +19,7 @@ use Drupal\user\EntityOwnerTrait;
* label = @Translation("OAuth2 token"),
* bundle_label = @Translation("Token type"),
* handlers = {
* "storage_schema" = "Drupal\simple_oauth\Entity\Oauth2TokenStorageSchema",
* "list_builder" = "Drupal\simple_oauth\Oauth2TokenListBuilder",
* "form" = {
* "delete" = "Drupal\simple_oauth\Entity\Form\Oauth2TokenDeleteForm",
......@@ -27,6 +28,9 @@ use Drupal\user\EntityOwnerTrait;
* },
* base_table = "oauth2_token",
* admin_permission = "administer simple_oauth entities",
* field_indexes = {
* "value"
* },
* entity_keys = {
* "id" = "id",
* "label" = "value",
......
<?php
namespace Drupal\simple_oauth\Entity;
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Entity\Sql\SqlContentEntityStorageSchema;
use Drupal\Core\Field\FieldStorageDefinitionInterface;
/**
* Defines the oauth2_token schema handler.
*/
class Oauth2TokenStorageSchema extends SqlContentEntityStorageSchema {
/**
* {@inheritdoc}
*
* Remove this method when the fix lands in core:
* https://www.drupal.org/project/drupal/issues/3005447
*/
public function onEntityTypeUpdate(EntityTypeInterface $entity_type, EntityTypeInterface $original): void {
parent::onEntityTypeUpdate($entity_type, $original);
$entity_schema = $this->getEntitySchema($entity_type, TRUE);
$schema_table = $entity_type->getDataTable() ?: $entity_type->getBaseTable();
$schema_indexes = $entity_schema[$schema_table]['indexes'];
foreach ($schema_indexes as $index_name => $index_fields) {
if (!$this->database->schema()->indexExists($schema_table, $index_name)) {
$this->database->schema()->addIndex($schema_table, $index_name, $index_fields, $entity_schema[$schema_table]);
}
}
}
/**
* {@inheritdoc}
*/
protected function getSharedTableFieldSchema(FieldStorageDefinitionInterface $storage_definition, $table_name, array $column_mapping): array {
$schema = parent::getSharedTableFieldSchema($storage_definition, $table_name, $column_mapping);
$entity_type = $this->entityTypeManager->getDefinition($storage_definition->getTargetEntityTypeId());
$field_indexes = $entity_type->get('field_indexes');
foreach ($field_indexes as $field_name) {
if ($field_name == $storage_definition->getName()) {
$this->addSharedTableFieldIndex($storage_definition, $schema);
}
}
return $schema;
}
}
......@@ -6,7 +6,7 @@ use Drupal\Component\Datetime\TimeInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Entity\Query\QueryException;
use Drupal\Core\Session\AccountInterface;
use Drupal\consumers\Entity\Consumer;
use Drupal\consumers\Entity\ConsumerInterface;
/**
* Service in charge of deleting or expiring tokens that cannot be used anymore.
......@@ -61,6 +61,7 @@ class ExpiredCollector {
*/
public function collect($limit = 0) {
$query = $this->tokenStorage->getQuery();
$query->accessCheck();
$query->condition('expire', $this->dateTime->getRequestTime(), '<');
// If limit available.
if (!empty($limit)) {
......@@ -83,6 +84,7 @@ class ExpiredCollector {
*/
public function collectForAccount(AccountInterface $account) {
$query = $this->tokenStorage->getQuery();
$query->accessCheck();
$query->condition('auth_user_id', $account->id());
$query->condition('bundle', 'refresh_token', '!=');
$entity_ids = $query->execute();
......@@ -115,14 +117,15 @@ class ExpiredCollector {
/**
* Collect all the tokens associated a particular client.
*
* @param \Drupal\consumers\Entity\Consumer $client
* @param \Drupal\consumers\Entity\ConsumerInterface $client
* The account.
*
* @return \Drupal\simple_oauth\Entity\Oauth2TokenInterface[]
* The tokens.
*/
public function collectForClient(Consumer $client) {
public function collectForClient(ConsumerInterface $client) {
$query = $this->tokenStorage->getQuery();
$query->accessCheck();
$query->condition('client', $client->id());
if (!$entity_ids = $query->execute()) {
return [];
......
......@@ -61,7 +61,7 @@ class ClientCredentialsOverrideGrant extends ClientCredentialsGrant {
$client_drupal_entities = \Drupal::entityTypeManager()
->getStorage('consumer')
->loadByProperties([
'uuid' => $client->getIdentifier(),
'client_id' => $client->getIdentifier(),
]);
$client_drupal_entity = reset($client_drupal_entities);
......
......@@ -4,7 +4,7 @@ namespace Drupal\simple_oauth\Plugin;
use Defuse\Crypto\Core;
use Drupal\Component\Plugin\Exception\PluginNotFoundException;
use Drupal\consumers\Entity\Consumer;
use Drupal\consumers\Entity\ConsumerInterface;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Config\ImmutableConfig;
use Drupal\Core\File\FileSystemInterface;
......@@ -133,7 +133,7 @@ class Oauth2GrantManager extends DefaultPluginManager implements Oauth2GrantMana
/**
* {@inheritdoc}
*/
public function getAuthorizationServer($grant_type, Consumer $client = NULL) {
public function getAuthorizationServer($grant_type, ConsumerInterface $client = NULL) {
try {
/** @var \Drupal\simple_oauth\Plugin\Oauth2GrantInterface $plugin */
$plugin = $this->createInstance($grant_type);
......