diff --git a/modules/simple_oauth_static_scope/simple_oauth_static_scope.info.yml b/modules/simple_oauth_static_scope/simple_oauth_static_scope.info.yml
index 4442743bbaca2c4a128806b056eab464887743e5..53f85533467cea77972154d9a265526bd413d8e3 100644
--- a/modules/simple_oauth_static_scope/simple_oauth_static_scope.info.yml
+++ b/modules/simple_oauth_static_scope/simple_oauth_static_scope.info.yml
@@ -1,7 +1,7 @@
 name: Simple OAuth static scope
 type: module
 description: 'Makes static (YAML) defined scopes available.'
-core_version_requirement: ^10.2 || ^11
+core_version_requirement: ^10.3 || ^11
 package: Authentication
 dependencies:
   - simple_oauth:simple_oauth
diff --git a/modules/simple_oauth_static_scope/src/Plugin/Oauth2Scope.php b/modules/simple_oauth_static_scope/src/Plugin/Oauth2Scope.php
index 1424a88f0159febec70029b43bab69b3e1f55a0f..608ec31d528942bb0e7cb5fe86730f3d3c70e1dd 100644
--- a/modules/simple_oauth_static_scope/src/Plugin/Oauth2Scope.php
+++ b/modules/simple_oauth_static_scope/src/Plugin/Oauth2Scope.php
@@ -108,4 +108,13 @@ class Oauth2Scope extends PluginBase implements Oauth2ScopePluginInterface, Cont
     );
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  public function getPermissions(): array {
+    $granularity = $this->getGranularity();
+    assert($granularity instanceof ScopeGranularityInterface);
+    return $granularity->getPermissions();
+  }
+
 }
diff --git a/simple_oauth.info.yml b/simple_oauth.info.yml
index 346c0f0793aa3395d0268aee3ed652036bdb0ee7..4527812c508c63bff1db934968d21c3572eb7371 100644
--- a/simple_oauth.info.yml
+++ b/simple_oauth.info.yml
@@ -1,7 +1,7 @@
 name: Simple OAuth & OpenID Connect
 type: module
 description: 'The OAuth 2.0 Authorization Framework'
-core_version_requirement: ^10.2 || ^11
+core_version_requirement: ^10.3 || ^11
 package: Authentication
 configure: oauth2_token.settings
 dependencies:
diff --git a/simple_oauth.services.yml b/simple_oauth.services.yml
index 1ac7cdaa8d5a9e3416787810051281f4995e2d8d..81649e7628520d5069770e656197bf8f78fabb97 100644
--- a/simple_oauth.services.yml
+++ b/simple_oauth.services.yml
@@ -24,6 +24,8 @@ services:
       - '@simple_oauth.page_cache_request_policy.disallow_oauth2_token_requests'
       - '@psr7.http_message_factory'
       - '@psr7.http_foundation_factory'
+      - '@request_stack'
+      - '@permission_checker'
     tags:
       - { name: authentication_provider, provider_id: oauth2, global: TRUE, priority: 35 }
   simple_oauth.page_cache_request_policy.disallow_oauth2_token_requests:
@@ -36,7 +38,16 @@ services:
     arguments:
       - '@Drupal\simple_oauth\EventSubscriber\ExceptionLoggingSubscriber.inner'
       - '@logger.channel.simple_oauth'
-
+  cache_context.oauth2_scopes:
+    class: Drupal\simple_oauth\Oauth2ScopeCacheContext
+    arguments: [ '@current_user' ]
+    tags:
+      - { name: cache.context }
+  access_policy.simple_oauth:
+    class: Drupal\simple_oauth\Oauth2AccessPolicy
+    arguments: [ '@simple_oauth.oauth2_scope.provider' ]
+    tags:
+      - { name: access_policy }
   simple_oauth.normalizer.oauth2_token:
     class: Drupal\simple_oauth\Normalizer\TokenEntityNormalizer
     arguments: [ '@entity_type.manager' ]
diff --git a/src/Authentication/Provider/SimpleOauthAuthenticationProvider.php b/src/Authentication/Provider/SimpleOauthAuthenticationProvider.php
index fb03015acb32c706a935c61c7d442516bda3ee87..6187c6a14234dc5c3bf87d2a0047f09ae7fa8fc3 100644
--- a/src/Authentication/Provider/SimpleOauthAuthenticationProvider.php
+++ b/src/Authentication/Provider/SimpleOauthAuthenticationProvider.php
@@ -4,6 +4,7 @@ namespace Drupal\simple_oauth\Authentication\Provider;
 
 use Drupal\Core\Authentication\AuthenticationProviderInterface;
 use Drupal\Core\Entity\EntityTypeManagerInterface;
+use Drupal\Core\Session\PermissionCheckerInterface;
 use Drupal\Core\StringTranslation\StringTranslationTrait;
 use Drupal\simple_oauth\Authentication\TokenAuthUser;
 use Drupal\simple_oauth\Exception\OAuthUnauthorizedHttpException;
@@ -13,6 +14,7 @@ use League\OAuth2\Server\Exception\OAuthServerException;
 use Symfony\Bridge\PsrHttpMessage\HttpFoundationFactoryInterface;
 use Symfony\Bridge\PsrHttpMessage\HttpMessageFactoryInterface;
 use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\HttpFoundation\RequestStack;
 
 /**
  * OAuth2 authentication provider.
@@ -23,68 +25,33 @@ class SimpleOauthAuthenticationProvider implements AuthenticationProviderInterfa
 
   use StringTranslationTrait;
 
-  /**
-   * The resource server factory.
-   *
-   * @var \Drupal\simple_oauth\Server\ResourceServerFactoryInterface
-   */
-  protected ResourceServerFactoryInterface $resourceServerFactory;
-
-  /**
-   * The entity type manager.
-   *
-   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
-   */
-  protected EntityTypeManagerInterface $entityTypeManager;
-
-  /**
-   * The request policy.
-   *
-   * @var \Drupal\simple_oauth\PageCache\SimpleOauthRequestPolicyInterface
-   */
-  protected SimpleOauthRequestPolicyInterface $oauthPageCacheRequestPolicy;
-
-  /**
-   * The HTTP message factory.
-   *
-   * @var \Symfony\Bridge\PsrHttpMessage\HttpMessageFactoryInterface
-   */
-  protected HttpMessageFactoryInterface $httpMessageFactory;
-
-  /**
-   * The HTTP foundation factory.
-   *
-   * @var \Symfony\Bridge\PsrHttpMessage\HttpFoundationFactoryInterface
-   */
-  protected HttpFoundationFactoryInterface $httpFoundationFactory;
-
   /**
    * Constructs an HTTP basic authentication provider object.
    *
-   * @param \Drupal\simple_oauth\Server\ResourceServerFactoryInterface $resource_server_factory
+   * @param \Drupal\simple_oauth\Server\ResourceServerFactoryInterface $resourceServerFactory
    *   The resource server factory.
-   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
+   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entityTypeManager
    *   The entity type manager service.
-   * @param \Drupal\simple_oauth\PageCache\SimpleOauthRequestPolicyInterface $page_cache_request_policy
+   * @param \Drupal\simple_oauth\PageCache\SimpleOauthRequestPolicyInterface $oauthPageCacheRequestPolicy
    *   The page cache request policy.
-   * @param \Symfony\Bridge\PsrHttpMessage\HttpMessageFactoryInterface $http_message_factory
+   * @param \Symfony\Bridge\PsrHttpMessage\HttpMessageFactoryInterface $httpMessageFactory
    *   The HTTP message factory.
-   * @param \Symfony\Bridge\PsrHttpMessage\HttpFoundationFactoryInterface $http_foundation_factory
+   * @param \Symfony\Bridge\PsrHttpMessage\HttpFoundationFactoryInterface $httpFoundationFactory
    *   The HTTP foundation factory.
+   * @param \Symfony\Component\HttpFoundation\RequestStack $requestStack
+   *   The request stack.
+   * @param \Drupal\Core\Session\PermissionCheckerInterface $permissionChecker
+   *   The permission checker service.
    */
   public function __construct(
-    ResourceServerFactoryInterface $resource_server_factory,
-    EntityTypeManagerInterface $entity_type_manager,
-    SimpleOauthRequestPolicyInterface $page_cache_request_policy,
-    HttpMessageFactoryInterface $http_message_factory,
-    HttpFoundationFactoryInterface $http_foundation_factory,
-  ) {
-    $this->resourceServerFactory = $resource_server_factory;
-    $this->entityTypeManager = $entity_type_manager;
-    $this->oauthPageCacheRequestPolicy = $page_cache_request_policy;
-    $this->httpMessageFactory = $http_message_factory;
-    $this->httpFoundationFactory = $http_foundation_factory;
-  }
+    protected readonly ResourceServerFactoryInterface $resourceServerFactory,
+    protected readonly EntityTypeManagerInterface $entityTypeManager,
+    protected readonly SimpleOauthRequestPolicyInterface $oauthPageCacheRequestPolicy,
+    protected readonly HttpMessageFactoryInterface $httpMessageFactory,
+    protected readonly HttpFoundationFactoryInterface $httpFoundationFactory,
+    protected readonly RequestStack $requestStack,
+    protected readonly PermissionCheckerInterface $permissionChecker,
+  ) {}
 
   /**
    * {@inheritdoc}
@@ -129,8 +96,12 @@ class SimpleOauthAuthenticationProvider implements AuthenticationProviderInterfa
       'value' => $auth_request->get('oauth_access_token_id'),
     ]);
     $token = reset($tokens);
-
-    $account = new TokenAuthUser($token);
+    $account = new TokenAuthUser(
+      $this->permissionChecker,
+      $token,
+      $this->httpMessageFactory,
+      $this->requestStack
+    );
 
     // Revoke the access token for the blocked user.
     if ($account->isBlocked() && $account->isAuthenticated()) {
diff --git a/src/Authentication/TokenAuthUser.php b/src/Authentication/TokenAuthUser.php
index 36853ea3d8b3025204b2b8c61ecc9a6e80a8a42c..f93f3a7ce462e742583562492d1100a3ffcf1892 100644
--- a/src/Authentication/TokenAuthUser.php
+++ b/src/Authentication/TokenAuthUser.php
@@ -7,10 +7,13 @@ use Drupal\Core\Entity\EntityStorageInterface;
 use Drupal\Core\Entity\EntityTypeInterface;
 use Drupal\Core\Session\AccountInterface;
 use Drupal\consumers\Entity\Consumer;
+use Drupal\Core\Session\PermissionCheckerInterface;
 use Drupal\simple_oauth\Entity\Oauth2TokenInterface;
 use Drupal\user\Entity\User;
 use Drupal\user\UserInterface;
 use League\OAuth2\Server\Exception\OAuthServerException;
+use Symfony\Bridge\PsrHttpMessage\HttpMessageFactoryInterface;
+use Symfony\Component\HttpFoundation\RequestStack;
 
 /**
  * The decorated user class with token information.
@@ -26,13 +29,6 @@ class TokenAuthUser implements TokenAuthUserInterface {
    */
   protected $subject;
 
-  /**
-   * The bearer token.
-   *
-   * @var \Drupal\simple_oauth\Entity\Oauth2TokenInterface
-   */
-  protected Oauth2TokenInterface $token;
-
   /**
    * The activated consumer instance.
    *
@@ -43,24 +39,33 @@ class TokenAuthUser implements TokenAuthUserInterface {
   /**
    * Constructs a TokenAuthUser object.
    *
+   * @param \Drupal\Core\Session\PermissionCheckerInterface $permissionChecker
+   *   The permission checker service.
    * @param \Drupal\simple_oauth\Entity\Oauth2TokenInterface $token
    *   The underlying token.
+   * @param \Symfony\Bridge\PsrHttpMessage\HttpMessageFactoryInterface $httpMessageFactory
+   *   The HTTP message factory.
+   * @param \Symfony\Component\HttpFoundation\RequestStack $requestStack
+   *   The request stack.
    *
    * @throws \League\OAuth2\Server\Exception\OAuthServerException
    *   When there is no user.
    */
-  public function __construct(Oauth2TokenInterface $token) {
+  public function __construct(
+    protected readonly PermissionCheckerInterface $permissionChecker,
+    protected readonly Oauth2TokenInterface $token,
+    protected readonly HttpMessageFactoryInterface $httpMessageFactory,
+    protected readonly RequestStack $requestStack,
+  ) {
     $this->consumer = $token->get('client')->entity;
 
     if (!$this->subject = $token->get('auth_user_id')->entity) {
       $this->subject = $this->consumer->get('user_id')->entity;
     }
     if (!$this->subject) {
-      $server_request = \Drupal::service('psr7.http_message_factory')
-        ->createRequest(\Drupal::request());
+      $server_request = $httpMessageFactory->createRequest($requestStack->getCurrentRequest());
       throw OAuthServerException::invalidClient($server_request);
     }
-    $this->token = $token;
   }
 
   /**
@@ -81,18 +86,18 @@ class TokenAuthUser implements TokenAuthUserInterface {
    * {@inheritdoc}
    */
   public function hasPermission($permission) {
+    if (!is_string($permission)) {
+      @trigger_error('Calling ' . __METHOD__ . '() with a $permission parameter of type other than string is deprecated in drupal:10.3.0 and will cause an error in drupal:11.0.0. See https://www.drupal.org/node/3411485', E_USER_DEPRECATED);
+      return FALSE;
+    }
     // When the 'auth_user_id' isn't available on the token (which can happen
     // with the 'client credentials' grant type):
     // has permission checks are then only performed on the scopes.
     if ($this->token->get('auth_user_id')->isEmpty()) {
-      return $this->token->hasPermission($permission);
-    }
-    // User #1 has all permissions.
-    if ((int) $this->id() === 1) {
-      return TRUE;
+      return $this->permissionChecker->hasPermission($permission, $this);
     }
 
-    return $this->token->hasPermission($permission) && $this->subject->hasPermission($permission);
+    return $this->permissionChecker->hasPermission($permission, $this) && $this->subject->hasPermission($permission);
   }
 
   /* ---------------------------------------------------------------------------
diff --git a/src/Entity/Oauth2Scope.php b/src/Entity/Oauth2Scope.php
index 618f318ce850148003883f5b03a6b09af1c120e1..7aeab01595893177a02e3335edf63ab37ef57ae9 100644
--- a/src/Entity/Oauth2Scope.php
+++ b/src/Entity/Oauth2Scope.php
@@ -257,6 +257,15 @@ class Oauth2Scope extends ConfigEntityBase implements Oauth2ScopeEntityInterface
     return $granularityCollection->get($this->granularity_id);
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  public function getPermissions(): array {
+    $granularity = $this->getGranularity();
+    assert($granularity instanceof ScopeGranularityInterface);
+    return $granularity->getPermissions();
+  }
+
   /**
    * {@inheritdoc}
    */
diff --git a/src/Oauth2AccessPolicy.php b/src/Oauth2AccessPolicy.php
new file mode 100644
index 0000000000000000000000000000000000000000..ec29edf2d91f89663d1463a6c68e24963868bf74
--- /dev/null
+++ b/src/Oauth2AccessPolicy.php
@@ -0,0 +1,47 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Drupal\simple_oauth;
+
+use Drupal\Core\Session\AccessPolicyBase;
+use Drupal\Core\Session\AccountInterface;
+use Drupal\Core\Session\CalculatedPermissionsItem;
+use Drupal\Core\Session\RefinableCalculatedPermissionsInterface;
+use Drupal\simple_oauth\Authentication\TokenAuthUserInterface;
+
+/**
+ * Grants permissions based on OAuth2 scopes.
+ */
+final class Oauth2AccessPolicy extends AccessPolicyBase {
+
+  public function __construct(protected Oauth2ScopeProviderInterface $scopeProvider) {}
+
+  /**
+   * {@inheritdoc}
+   */
+  public function calculatePermissions(AccountInterface $account, string $scope): RefinableCalculatedPermissionsInterface {
+    $calculated_permissions = parent::calculatePermissions($account, $scope);
+
+    if (!$account instanceof TokenAuthUserInterface) {
+      return $calculated_permissions;
+    }
+
+    $token = $account->getToken();
+    foreach ($token->get('scopes')->getScopes() as $oauth2_scope) {
+      $calculated_permissions
+        ->addItem(new CalculatedPermissionsItem($this->scopeProvider->getPermissions($oauth2_scope)))
+        ->addCacheableDependency($oauth2_scope);
+    }
+
+    return $calculated_permissions;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getPersistentCacheContexts(): array {
+    return ['oauth2_scopes'];
+  }
+
+}
diff --git a/src/Oauth2ScopeCacheContext.php b/src/Oauth2ScopeCacheContext.php
new file mode 100644
index 0000000000000000000000000000000000000000..d89ca2e6273725ffac590deec3d068dd9f2b71e3
--- /dev/null
+++ b/src/Oauth2ScopeCacheContext.php
@@ -0,0 +1,57 @@
+<?php
+
+namespace Drupal\simple_oauth;
+
+use Drupal\Core\Cache\CacheableMetadata;
+use Drupal\Core\Cache\Context\CalculatedCacheContextInterface;
+use Drupal\Core\Session\AccountProxyInterface;
+use Drupal\simple_oauth\Authentication\TokenAuthUserInterface;
+
+/**
+ * Defines the Oauth2ScopeCacheContext service, for "per scope" caching.
+ */
+class Oauth2ScopeCacheContext implements CalculatedCacheContextInterface {
+
+  /**
+   * Constructs a new Oauth2ScopeCacheContext class.
+   *
+   * @param \Drupal\Core\Session\AccountProxyInterface $account
+   *   The current user.
+   */
+  public function __construct(protected AccountProxyInterface $account) {}
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getLabel() {
+    return t("OAuth2 scopes");
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getContext($oauth2_scope = NULL) {
+    $account = $this->account->getAccount();
+    if (!$account instanceof TokenAuthUserInterface) {
+      return '';
+    }
+
+    $token = $account->getToken();
+    $scope_names = array_map(function (Oauth2ScopeInterface $scope) {
+      return $scope->getName();
+    }, $token->get('scopes')->getScopes());
+
+    if ($oauth2_scope === NULL) {
+      return implode(',', $scope_names);
+    }
+    return (in_array($oauth2_scope, $scope_names) ? 'true' : 'false');
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getCacheableMetadata($scope = NULL) {
+    return (new CacheableMetadata())->setCacheTags(['user:' . $this->account->id()]);
+  }
+
+}
diff --git a/src/Oauth2ScopeInterface.php b/src/Oauth2ScopeInterface.php
index 2c6619657654fc28902d1dcdb8709b91b6380dbd..d0e812594b33e0948dc508526b4ca7aab7c6ee7b 100644
--- a/src/Oauth2ScopeInterface.php
+++ b/src/Oauth2ScopeInterface.php
@@ -99,4 +99,12 @@ interface Oauth2ScopeInterface {
    */
   public function getGranularity(): ?ScopeGranularityInterface;
 
+  /**
+   * Get the referenced permissions.
+   *
+   * @return array
+   *   Returns the permissions.
+   */
+  public function getPermissions(): array;
+
 }
diff --git a/src/Oauth2ScopeProvider.php b/src/Oauth2ScopeProvider.php
index fb6418234f67327b8a716c28431799b245d38bb3..4b8913e0b606bc479a88f9da15b13d52f5c243d0 100644
--- a/src/Oauth2ScopeProvider.php
+++ b/src/Oauth2ScopeProvider.php
@@ -94,6 +94,25 @@ class Oauth2ScopeProvider implements Oauth2ScopeProviderInterface {
     return FALSE;
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  public function getPermissions(Oauth2ScopeInterface $scope): array {
+    if (!$scope->isUmbrella()) {
+      $granularity = $scope->getGranularity();
+      assert($granularity instanceof ScopeGranularityInterface);
+      return $granularity->getPermissions();
+    }
+
+    $permissions = [];
+    $children = $this->loadChildren($scope->id());
+    foreach ($children as $child) {
+      $permissions = array_unique(array_merge($permissions, $child->getPermissions()));
+    }
+
+    return $permissions;
+  }
+
   /**
    * Adds a permission to the flatten permission tree.
    *
diff --git a/src/Oauth2ScopeProviderInterface.php b/src/Oauth2ScopeProviderInterface.php
index 2b09874a0bfa6b672073a57fef94c4c87f70dee4..53adc01e1891aa1e39851d597842d48cfe1b63fa 100644
--- a/src/Oauth2ScopeProviderInterface.php
+++ b/src/Oauth2ScopeProviderInterface.php
@@ -20,4 +20,12 @@ interface Oauth2ScopeProviderInterface extends Oauth2ScopeAdapterInterface {
    */
   public function scopeHasPermission(string $permission, Oauth2ScopeInterface $scope): bool;
 
+  /**
+   * Get the referenced permissions.
+   *
+   * @return array
+   *   Returns the permissions.
+   */
+  public function getPermissions(Oauth2ScopeInterface $scope): array;
+
 }
diff --git a/src/Plugin/ScopeGranularity/Permission.php b/src/Plugin/ScopeGranularity/Permission.php
index ba7c4e9363c67df4c8892f9eb43c67c13ea83763..467cf1dc42bc5714ac7a3514c45b54c9a09b5ff3 100644
--- a/src/Plugin/ScopeGranularity/Permission.php
+++ b/src/Plugin/ScopeGranularity/Permission.php
@@ -76,6 +76,13 @@ class Permission extends ScopeGranularityBase implements ContainerFactoryPluginI
     return $this->getConfiguration()['permission'] === $permission;
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  public function getPermissions(): array {
+    return [$this->getConfiguration()['permission']];
+  }
+
   /**
    * {@inheritdoc}
    */
diff --git a/src/Plugin/ScopeGranularity/Role.php b/src/Plugin/ScopeGranularity/Role.php
index 924a736a8d1cf4831e9fd02e20b55361b8b04e09..805adc5d49b1328c371ae201c183ee2ca44810ff 100644
--- a/src/Plugin/ScopeGranularity/Role.php
+++ b/src/Plugin/ScopeGranularity/Role.php
@@ -11,6 +11,7 @@ use Drupal\Core\StringTranslation\TranslatableMarkup;
 use Drupal\simple_oauth\Attribute\ScopeGranularity;
 use Drupal\simple_oauth\Oauth2ScopeInterface;
 use Drupal\simple_oauth\Plugin\ScopeGranularityBase;
+use Drupal\user\RoleInterface;
 use Drupal\user\RoleStorage;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 
@@ -87,6 +88,33 @@ class Role extends ScopeGranularityBase implements ContainerFactoryPluginInterfa
     return $role_storage->isPermissionInRoles($permission, $rolesToCheck);
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  public function getPermissions(): array {
+    $role = $this->getConfiguration()['role'];
+
+    $lockedRoles = [
+      AccountInterface::AUTHENTICATED_ROLE,
+      AccountInterface::ANONYMOUS_ROLE,
+    ];
+    $rolesToCheck = !in_array($role, $lockedRoles)
+      ? [AccountInterface::AUTHENTICATED_ROLE, $role]
+      : [$role];
+
+    $role_storage = $this->entityTypeManager->getStorage('user_role');
+    assert($role_storage instanceof RoleStorage);
+
+    $permissions = [];
+    foreach ($rolesToCheck as $roleToCheck) {
+      $role = $role_storage->load($roleToCheck);
+      assert($role instanceof RoleInterface);
+      $permissions = array_unique(array_merge($permissions, $role->getPermissions()));
+    }
+
+    return $permissions;
+  }
+
   /**
    * {@inheritdoc}
    */
diff --git a/src/Plugin/ScopeGranularityInterface.php b/src/Plugin/ScopeGranularityInterface.php
index eb94b9bb433f9aa924b9a9fcc0f54b4f1c235fdb..36d6b3f308df2d45f95a06450cd6d45e305106be 100644
--- a/src/Plugin/ScopeGranularityInterface.php
+++ b/src/Plugin/ScopeGranularityInterface.php
@@ -32,4 +32,12 @@ interface ScopeGranularityInterface extends ConfigurableInterface, PluginFormInt
    */
   public function hasPermission(string $permission): bool;
 
+  /**
+   * Returns a list of permissions assigned to the scope.
+   *
+   * @return array
+   *   The permissions assigned to the scope.
+   */
+  public function getPermissions(): array;
+
 }
diff --git a/tests/modules/simple_oauth_test/src/Plugin/ScopeGranularity/TestGranularity.php b/tests/modules/simple_oauth_test/src/Plugin/ScopeGranularity/TestGranularity.php
index e483fdbcdc90e04dd4658b57e94dc22bd05f2531..f6843efce9aaa8ce15b3e43b17a43adcbea013bc 100644
--- a/tests/modules/simple_oauth_test/src/Plugin/ScopeGranularity/TestGranularity.php
+++ b/tests/modules/simple_oauth_test/src/Plugin/ScopeGranularity/TestGranularity.php
@@ -58,6 +58,13 @@ class TestGranularity extends ScopeGranularityBase {
     return TRUE;
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  public function getPermissions(): array {
+    return [];
+  }
+
   /**
    * {@inheritdoc}
    */
diff --git a/tests/src/Unit/Authentication/Provider/SimpleOauthAuthenticationTest.php b/tests/src/Unit/Authentication/Provider/SimpleOauthAuthenticationTest.php
index 6671ac7327beea6bc25eeee1df4b63140e46edaf..6f2762d19d16f560a7da2cf6c0ce858b76dc431d 100644
--- a/tests/src/Unit/Authentication/Provider/SimpleOauthAuthenticationTest.php
+++ b/tests/src/Unit/Authentication/Provider/SimpleOauthAuthenticationTest.php
@@ -5,6 +5,7 @@ namespace Drupal\Tests\simple_oauth\Unit\Authentication\Provider;
 use Drupal\Core\Authentication\AuthenticationProviderInterface;
 use Drupal\Core\Entity\EntityTypeManagerInterface;
 use Drupal\Core\PageCache\RequestPolicyInterface;
+use Drupal\Core\Session\PermissionCheckerInterface;
 use Drupal\TestTools\Random;
 use Drupal\Tests\UnitTestCase;
 use Drupal\simple_oauth\Authentication\Provider\SimpleOauthAuthenticationProvider;
@@ -15,6 +16,7 @@ use Prophecy\PhpUnit\ProphecyTrait;
 use Symfony\Bridge\PsrHttpMessage\HttpFoundationFactoryInterface;
 use Symfony\Bridge\PsrHttpMessage\HttpMessageFactoryInterface;
 use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\HttpFoundation\RequestStack;
 
 /**
  * @coversDefaultClass \Drupal\simple_oauth\Authentication\Provider\SimpleOauthAuthenticationProvider
@@ -48,12 +50,16 @@ class SimpleOauthAuthenticationTest extends UnitTestCase {
     $this->oauthPageCacheRequestPolicy = new DisallowSimpleOauthRequests();
     $http_message_factory = $this->prophesize(HttpMessageFactoryInterface::class);
     $http_foundation_factory = $this->prophesize(HttpFoundationFactoryInterface::class);
+    $request_stack = $this->prophesize(RequestStack::class);
+    $permission_checker = $this->prophesize(PermissionCheckerInterface::class);
     $this->provider = new SimpleOauthAuthenticationProvider(
       $resource_server_factory->reveal(),
       $entity_type_manager->reveal(),
       $this->oauthPageCacheRequestPolicy,
       $http_message_factory->reveal(),
       $http_foundation_factory->reveal(),
+      $request_stack->reveal(),
+      $permission_checker->reveal()
     );
   }