diff --git a/composer.json b/composer.json
new file mode 100644
index 0000000000000000000000000000000000000000..b8c834ccc6c2afd2b98f808f5f14b251d76a4f12
--- /dev/null
+++ b/composer.json
@@ -0,0 +1,7 @@
+{
+    "name": "drupal/restrict_by_ip",
+    "type": "drupal-module",
+    "license": "GPL-2.0-or-later",
+    "minimum-stability": "stable",
+    "require": {}
+}
diff --git a/restrict_by_ip.info.yml b/restrict_by_ip.info.yml
index 63ab66a52f58a292b89557003b807e4a737e0f1c..21934e89461181ac7cc11a05f5c1a4ef47631934 100644
--- a/restrict_by_ip.info.yml
+++ b/restrict_by_ip.info.yml
@@ -2,5 +2,5 @@ name: Restrict By IP
 description: Enables limiting user login and role access to specific IP Addresses.
 type: module
 package: Access control
-core_version_requirement: ^8 || ^9
+core_version_requirement: ^9.5 || ^10
 configure: restrict_by_ip.general_settings
diff --git a/restrict_by_ip.module b/restrict_by_ip.module
index e5d8b6657cef509dff2cd461d3fadc6398e3dee7..b09393d74533de457c6708d4fa8b06d3ec714085 100644
--- a/restrict_by_ip.module
+++ b/restrict_by_ip.module
@@ -1,5 +1,6 @@
 <?php
 
+use Drupal\restrict_by_ip\Exception\InvalidIPException;
 /**
  * @file
  * Restrict logins or roles to IP addresses on the allowed list.
@@ -21,36 +22,6 @@ function restrict_by_ip_help($section) {
   return $output;
 }
 
-/**
- * Implements hook_init().
- *
- * @TODO
- */
-function restrict_by_ip_init() {
-  global $user;
-  // Login restriction check moved here to prevent access from stale session data
-  _restrict_by_ip_login($user);
-}
-
-/**
- * Implements hook_boot().
- *
- * @TODO
- */
-function restrict_by_ip_boot() {
-  global $user;
-  // Call the function early in boot process to check/strip roles
-  restrict_by_ip_role_check($user);
-}
-
-/**
- * Implements hook_user_login().
- */
-function restrict_by_ip_user_login($account) {
-  $login_firewall = \Drupal::service('restrict_by_ip.login_firewall');
-  $login_firewall->execute($account);
-}
-
 /**
  * Implements hook_user_delete().
  */
@@ -109,7 +80,7 @@ function restrict_by_ip_user_profile_validate($form, &$form_state) {
       try {
         $ip_tools->validateIP($ip);
       }
-      catch (\Drupal\restrict_by_ip\Exception\InvalidIPException $e) {
+      catch (InvalidIPException $e) {
         $form_state->setErrorByName('restrict_by_ip_address', t($e->getMessage()));
       }
     }
@@ -142,33 +113,6 @@ function restrict_by_ip_user_role_delete($role) {
   $config->clear('role.' . $role->id())->save();
 }
 
-/**
- * Perform an IP restriction check for all roles belonging to the given user.
- *
- * @TODO
- */
-function restrict_by_ip_role_check(&$user){
-  $ip2check = _restrict_by_ip_get_ip();
-  // Check each role belonging to specified user
-  foreach ($user->roles as $rid => $name) {
-    $form_name = _restrict_by_ip_hash_role_name($name);
-    $ranges = variable_get('restrict_by_ip_role_' . $form_name, '');
-    // Only check IP if an IP restriction is set for this role
-    if (!empty($ranges)) {
-      $ipaddresses = explode(';', $ranges);
-      $match = FALSE;
-      foreach ($ipaddresses as $ipaddress) {
-        if (_restrict_by_ip_cidrcheck($ip2check, $ipaddress)) {
-          $match = TRUE;
-        }
-      }
-      if (!$match) {
-        unset($user->roles[$rid]);
-      }
-    }
-  }
-}
-
 /**
  * When a user entity is loaded, remove any roles that are restricted based on
  * IP allow lists.
diff --git a/restrict_by_ip.services.yml b/restrict_by_ip.services.yml
index 669a2faeb2812c410e163c089014cc5392ded581..265575836a88de8039514493074218c3367a9c52 100644
--- a/restrict_by_ip.services.yml
+++ b/restrict_by_ip.services.yml
@@ -4,12 +4,16 @@ services:
     arguments: ["@config.factory"]
   restrict_by_ip.login_firewall:
     class: Drupal\restrict_by_ip\LoginFirewall
-    arguments: ["@restrict_by_ip.ip_tools","@config.factory","@logger.factory","@unrouted_url_assembler"]
+    arguments: ["@restrict_by_ip.ip_tools","@config.factory","@logger.factory","@unrouted_url_assembler","@session_manager","@current_user"]
   restrict_by_ip.firewall_subscriber:
     class: Drupal\restrict_by_ip\EventSubscriber\FirewallSubscriber
     arguments: ["@restrict_by_ip.login_firewall","@current_user"]
     tags:
       - { name: event_subscriber }
   restrict_by_ip.role_firewall:
-      class: Drupal\restrict_by_ip\RoleFirewall
-      arguments: ["@restrict_by_ip.ip_tools","@config.factory","@entity_type.manager"]
\ No newline at end of file
+    class: Drupal\restrict_by_ip\RoleFirewall
+    arguments: ["@restrict_by_ip.ip_tools","@config.factory","@entity_type.manager"]
+  restrict_by_ip.current_user:
+    class: Drupal\restrict_by_ip\Session\RestrictedAccountProxy
+    decorates: current_user
+    arguments: ["@restrict_by_ip.current_user.inner", "@event_dispatcher", "@entity_type.manager", "@restrict_by_ip.role_firewall"]
diff --git a/src/EventSubscriber/FirewallSubscriber.php b/src/EventSubscriber/FirewallSubscriber.php
index c307c66d218935a917297046b36d2b8b3f25344e..b5f047484ee5fab830bdebace3b135b48203da53 100644
--- a/src/EventSubscriber/FirewallSubscriber.php
+++ b/src/EventSubscriber/FirewallSubscriber.php
@@ -2,10 +2,10 @@
 
 namespace Drupal\restrict_by_ip\EventSubscriber;
 
+use Symfony\Component\HttpKernel\Event\RequestEvent;
 use Symfony\Component\EventDispatcher\EventSubscriberInterface;
 use Drupal\Core\Session\AccountInterface;
 use Drupal\restrict_by_ip\LoginFirewallInterface;
-use Symfony\Component\HttpKernel\Event\GetResponseEvent;
 
 /**
  * Triggers the restrict by IP login firewall.
@@ -51,11 +51,13 @@ class FirewallSubscriber implements EventSubscriberInterface {
   /**
    * This method is called whenever the kernel.request event is dispatched.
    *
-   * @param \Symfony\Component\HttpKernel\Event\GetResponseEvent $event
+   * @param \Symfony\Component\HttpKernel\Event\RequestEvent $event
    *   The event.
    */
-  public function loginFirewall(GetResponseEvent $event) {
-    $this->loginFirewall->execute($this->currentUser);
+  public function loginFirewall(RequestEvent $event) {
+    if ($response = $this->loginFirewall->execute($this->currentUser)) {
+      $event->setResponse($response);
+    }
   }
 
 }
diff --git a/src/Form/UserSettingsForm.php b/src/Form/UserSettingsForm.php
index 3627b1f159eddfe48b152e7d9c325f3ffdb0e758..9920714d9812d2834e30088320139b5ee9e30710 100644
--- a/src/Form/UserSettingsForm.php
+++ b/src/Form/UserSettingsForm.php
@@ -2,6 +2,7 @@
 
 namespace Drupal\restrict_by_ip\Form;
 
+use Drupal\user\Entity\User;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 use Drupal\Core\Form\ConfigFormBase;
 use Drupal\Core\Form\FormStateInterface;
@@ -67,7 +68,7 @@ class UserSettingsForm extends ConfigFormBase {
 
     // Current restrictions.
     foreach ($config->get('user') as $key => $value) {
-      $account = \Drupal\user\Entity\User::load($key);
+      $account = User::load($key);
       $form['restrict_by_ip_user_' . $key] = [
         '#type' => 'textfield',
         '#title' => $this->t('@name user IP range', ['@name' => $account->label()]),
diff --git a/src/LoginFirewall.php b/src/LoginFirewall.php
index fe64f2535fa197a3a29b679fd2d194d8035fb052..9dbc44178ff5bb06584334cb8cfe386454039284 100644
--- a/src/LoginFirewall.php
+++ b/src/LoginFirewall.php
@@ -2,13 +2,14 @@
 
 namespace Drupal\restrict_by_ip;
 
+use Drupal\Core\Session\AnonymousUserSession;
+use Drupal\Core\Session\SessionManagerInterface;
 use Symfony\Component\HttpFoundation\RedirectResponse;
 use Drupal\Core\Config\ConfigFactoryInterface;
 use Drupal\Core\Logger\LoggerChannelFactoryInterface;
 use Drupal\Core\Url;
 use Drupal\Core\Utility\UnroutedUrlAssemblerInterface;
 use Drupal\Core\Session\AccountInterface;
-use Drupal\restrict_by_ip\IPToolsInterface;
 use Drupal\restrict_by_ip\Exception\IPOutOfRangeException;
 
 /**
@@ -22,17 +23,23 @@ class LoginFirewall implements LoginFirewallInterface {
   protected $config;
   protected $logger;
   protected $urlGenerator;
+  protected $sessionManager;
+  protected $currentUser;
 
   public function __construct(
     IPToolsInterface $ip_tools,
     ConfigFactoryInterface $config_factory,
     LoggerChannelFactoryInterface $logger_factory,
-    UnroutedUrlAssemblerInterface $url_generator) {
+    UnroutedUrlAssemblerInterface $url_generator,
+    SessionManagerInterface $session_manager,
+    AccountInterface $current_user) {
 
     $this->ipTools = $ip_tools;
     $this->config = $config_factory->get('restrict_by_ip.settings');
     $this->logger = $logger_factory->get('restrict_by_ip');
     $this->urlGenerator = $url_generator;
+    $this->sessionManager = $session_manager;
+    $this->currentUser = $current_user;
   }
 
   /**
@@ -48,7 +55,17 @@ class LoginFirewall implements LoginFirewallInterface {
         '@ip' => $user_ip,
       ]));
 
-      user_logout();
+      // If the user was already logged in when this setting was invoked, we
+      // do need to destroy the session, but we can't call \user_logout if the
+      // user is not logged in because it will try to destroy an uninitialized
+      // session.
+      /** @var SessionManagerInterface $sessionManager */
+      $sessionManager = $this->sessionManager;
+      if ($sessionManager->isStarted()) {
+        $sessionManager->destroy();
+      }
+      $user = $this->currentUser;
+      $user->setAccount(new AnonymousUserSession());
 
       // Redirect after logout.
       $path = $this->config->get('error_page');
@@ -61,7 +78,7 @@ class LoginFirewall implements LoginFirewallInterface {
       }
 
       $response = new RedirectResponse($redirect, RedirectResponse::HTTP_FOUND);
-      $response->send();
+      return $response;
     }
   }
 
diff --git a/src/RestrictByIpServiceProvider.php b/src/RestrictByIpServiceProvider.php
deleted file mode 100644
index aa8dd328ab827d129710d3992623fddecf6ddb5e..0000000000000000000000000000000000000000
--- a/src/RestrictByIpServiceProvider.php
+++ /dev/null
@@ -1,35 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains Drupal\restrict_by_ip\RestrictByIpServiceProvider
- */
-
-namespace Drupal\restrict_by_ip;
-
-use Symfony\Component\DependencyInjection\Definition;
-use Symfony\Component\DependencyInjection\Reference;
-use Drupal\Core\DependencyInjection\ServiceProviderBase;
-use Drupal\Core\DependencyInjection\ContainerBuilder;
-
-/**
- * Rename current_user service and replace with one provided by restrict_by_ip
- * module.
- */
-class RestrictByIpServiceProvider extends ServiceProviderBase {
-
-  /**
-   * {@inheritdoc}
-   */
-  public function alter(ContainerBuilder $container) {
-    // Rename current_user service.
-    $coreService = $container->getDefinition('current_user');
-    $container->setDefinition('restrict_by_ip.current_user', $coreService);
-
-    // Register this modules class as default for current_user service.
-    $newService = new Definition('Drupal\restrict_by_ip\Session\AccountProxy');
-    $newService->addArgument(new Reference('restrict_by_ip.current_user'));
-    $newService->addArgument(new Reference('restrict_by_ip.role_firewall'));
-    $container->setDefinition('current_user', $newService);
-  }
-}
\ No newline at end of file
diff --git a/src/Session/AccountProxy.php b/src/Session/AccountProxy.php
deleted file mode 100644
index cce0b48d1b0515eea19c3285e1377f7ac980c07e..0000000000000000000000000000000000000000
--- a/src/Session/AccountProxy.php
+++ /dev/null
@@ -1,174 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\restrict_by_ip\Session\AccountProxy.
- */
-
-namespace Drupal\restrict_by_ip\Session;
-
-use Drupal\Core\Session\AccountProxyInterface;
-use Drupal\Core\Session\AccountInterface;
-use Drupal\restrict_by_ip\RoleFirewallInterface;
-
-/**
- * When the current user is loaded, remove any roles that are restricted based
- * on the IP allow list. Proxy all other method calls to the original
- * current_user service.
- */
-class AccountProxy implements AccountProxyInterface {
-
-  /**
-   * The original current_user service.
-   *
-   * @var \Drupal\Core\Session\AccountProxyInterface
-   */
-  protected $original;
-
-  protected $roleFirewall;
-
-  public function __construct(
-    AccountProxyInterface $original,
-    RoleFirewallInterface $role_firewall) {
-
-    $this->original = $original;
-    $this->roleFirewall = $role_firewall;
-  }
-
-  /**
-   * Return roles for this user, less any that are restricted.
-   *
-   * @param bool $exclude_locked_roles
-   *   (optional) If TRUE, locked roles (anonymous/authenticated) are not returned.
-   *
-   * @return array
-   *   List of role IDs.
-   */
-  public function getRoles($exclude_locked_roles = FALSE) {
-    $roles = $this->original->getRoles($exclude_locked_roles);
-    $remove_roles = $this->roleFirewall->rolesToRemove();
-
-    return array_diff($roles, $remove_roles);
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function hasPermission($permission) {
-    // User #1 has all privileges.
-    if ((int) $this->id() === 1) {
-      return TRUE;
-    }
-
-    return $this->getRoleStorage()->isPermissionInRoles($permission, $this->getRoles());
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function setAccount(AccountInterface $account) {
-    $this->original->setAccount($account);
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getAccount() {
-    return $this->original->getAccount();
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function id() {
-    return $this->original->id();
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function isAuthenticated() {
-    return $this->original->isAuthenticated();
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function isAnonymous() {
-    return $this->original->isAnonymous();
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getPreferredLangcode($fallback_to_default = TRUE) {
-    return $this->original->getPreferredLangcode($fallback_to_default);
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getPreferredAdminLangcode($fallback_to_default = TRUE) {
-    return $this->original->getPreferredAdminLangcode($fallback_to_default);
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getUsername() {
-    return $this->original->getUsername();
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getAccountName() {
-    return $this->original->getAccountName();
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getDisplayName() {
-    return $this->original->getDisplayName();
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getEmail() {
-    return $this->original->getEmail();
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getTimeZone() {
-    return $this->original->getTimeZone();
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getLastAccessedTime() {
-    return $this->original->getLastAccessedTime();
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function setInitialAccountId($account_id) {
-    $this->original->setInitialAccountId($account_id);
-  }
-
-  /**
-   * Returns the role storage object.
-   *
-   * @return \Drupal\user\RoleStorageInterface
-   *   The role storage object.
-   */
-  protected function getRoleStorage() {
-    return \Drupal::entityTypeManager()->getStorage('user_role');
-  }
-
-}
diff --git a/src/Session/RestrictedAccountProxy.php b/src/Session/RestrictedAccountProxy.php
new file mode 100644
index 0000000000000000000000000000000000000000..9a9d198aa1295ff036dc9323c31e99ec09b1efa2
--- /dev/null
+++ b/src/Session/RestrictedAccountProxy.php
@@ -0,0 +1,128 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\restrict_by_ip\Session\AccountProxy.
+ */
+
+namespace Drupal\restrict_by_ip\Session;
+
+use Drupal\Core\Entity\EntityTypeManagerInterface;
+use Drupal\Core\Session\AccountProxy;
+use Drupal\Core\Session\AccountProxyInterface;
+use Drupal\Core\Session\AnonymousUserSession;
+use Drupal\restrict_by_ip\RoleFirewallInterface;
+use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
+
+/**
+ * When the current user is loaded, remove any roles that are restricted based
+ * on IP whitelists. Proxy all other method calls to the original current_user
+ * service.
+ */
+class RestrictedAccountProxy extends AccountProxy {
+
+  /**
+   * The original current_user service.
+   *
+   * @var \Drupal\Core\Session\AccountProxyInterface
+   */
+  protected $original;
+
+  /**
+   * Entity Type Manager.
+   *
+   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
+   */
+  protected $entityTypeManager;
+
+  /**
+   * Role Firewall.
+   *
+   * @var \Drupal\restrict_by_ip\RoleFirewallInterface
+   */
+  protected $roleFirewall;
+
+  /**
+   * Construct a RestrictedAccountProxy object.
+   *
+   * @param \Drupal\Core\Session\AccountProxyInterface $original
+   *   The original current_user we're decorating.
+   * @param \Symfony\Contracts\EventDispatcher\EventDispatcherInterface $eventDispatcher
+   *   Event Dispatcher.
+   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entityTypeManager
+   *   Entity Type Manager.
+   * @param \Drupal\restrict_by_ip\RoleFirewallInterface $role_firewall
+   *   Role Firewall.
+   */
+  public function __construct(
+    AccountProxyInterface      $original,
+    EventDispatcherInterface   $eventDispatcher,
+    EntityTypeManagerInterface $entityTypeManager,
+    RoleFirewallInterface      $role_firewall) {
+    parent::__construct($eventDispatcher);
+    $this->original = $original;
+    $this->entityTypeManager = $entityTypeManager;
+    $this->roleFirewall = $role_firewall;
+  }
+
+  /**
+   * Return roles for this user, less any that are restricted.
+   *
+   * @param bool $exclude_locked_roles
+   *   (optional) If TRUE, locked roles (anonymous/authenticated) are not returned.
+   *
+   * @return array
+   *   List of role IDs.
+   */
+  public function getRoles($exclude_locked_roles = FALSE) {
+    $roles = $this->getAccount()->getRoles($exclude_locked_roles);
+    $remove_roles = $this->roleFirewall->rolesToRemove();
+
+    return array_diff($roles, $remove_roles);
+  }
+
+  /**
+   * {@inheritdoc}
+   *
+   * We need to duplicate this method instead of pointing at the original
+   * because $this->id doesn't get set on the original.
+   */
+  public function getAccount() {
+    if (!isset($this->account)) {
+      if ($this->id) {
+        // After the container is rebuilt, DrupalKernel sets the initial
+        // account to the id of the logged in user. This is necessary in order
+        // to refresh the user account reference here.
+        $this->setAccount($this->loadUserEntity($this->id));
+      }
+      else {
+        $this->account = new AnonymousUserSession();
+      }
+    }
+
+    return $this->account;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function hasPermission($permission) {
+    // User #1 has all privileges.
+    if ((int) $this->id() === 1) {
+      return TRUE;
+    }
+
+    return $this->getRoleStorage()->isPermissionInRoles($permission, $this->getRoles());
+  }
+
+  /**
+   * Returns the role storage object.
+   *
+   * @return \Drupal\Core\Entity\EntityStorageInterface
+   *   The role storage object.
+   */
+  protected function getRoleStorage() {
+    return $this->entityTypeManager->getStorage('user_role');
+  }
+
+}
diff --git a/tests/src/Functional/LoginTest.php b/tests/src/Functional/LoginTest.php
index 2745983e3052abde84898d16fd47944b36f49973..930a5e139312888b88039afa1dc133e9a432e888 100644
--- a/tests/src/Functional/LoginTest.php
+++ b/tests/src/Functional/LoginTest.php
@@ -135,6 +135,8 @@ class LoginTest extends RestrictByIPWebTestBase {
     $this->drupalGet(Url::fromRoute('user.login'));
     $this->submitForm($edit, t('Log in'));
 
+    // @todo: This only proves the user isn't on the account page.
+    // The redirect in LoginFirewall also sends the user elsewhere.
     $this->assertSession()->pageTextNotContains('Member for');
   }
 
diff --git a/tests/src/Functional/RedirectTest.php b/tests/src/Functional/RedirectTest.php
index 347a10af4ccaf7f82dd4bece9e73621f42702737..3eee954f6e92b24ff11db70c9f3d1e4a2751588f 100644
--- a/tests/src/Functional/RedirectTest.php
+++ b/tests/src/Functional/RedirectTest.php
@@ -23,7 +23,7 @@ class RedirectTest extends RestrictByIPWebTestBase {
    *
    * @var array
    */
-  public static $modules = [
+  protected static $modules = [
     'restrict_by_ip',
     'node',
   ];
@@ -31,7 +31,7 @@ class RedirectTest extends RestrictByIPWebTestBase {
   /**
    * {@inheritdoc}
    */
-  public function setUp() {
+  public function setUp(): void {
     parent::setUp();
 
     // Create a page users will get redirected to when denied login.
diff --git a/tests/src/Functional/RestrictByIPWebTestBase.php b/tests/src/Functional/RestrictByIPWebTestBase.php
index aaf8947623987c2dffd0cfce7d705945158de29f..cd13a41fbd23c40504c44038388d4fc239964537 100644
--- a/tests/src/Functional/RestrictByIPWebTestBase.php
+++ b/tests/src/Functional/RestrictByIPWebTestBase.php
@@ -56,7 +56,7 @@ abstract class RestrictByIPWebTestBase extends BrowserTestBase {
   /**
    * {@inheritdoc}
    */
-  public function setUp() {
+  public function setUp(): void {
     // Enable modules needed for these tests.
     parent::setUp();
 
@@ -75,7 +75,7 @@ abstract class RestrictByIPWebTestBase extends BrowserTestBase {
     $this->drupalLogin($adminUser);
     $this->drupalGet('admin/config/people/restrict_by_ip/login');
     $pageContent = $this->getTextContent();
-    preg_match('#is (.*?). If#', $pageContent, $matches);
+    preg_match('#is (.*?)\. If#', $pageContent, $matches);
     $this->drupalLogout();
 
     // The IP address when testing if client DOES matches restrictions.
diff --git a/tests/src/Functional/RoleTest.php b/tests/src/Functional/RoleTest.php
index a2cd212f08816b7254df131790546d33f5ffc0d3..b35191e17cf6cb5e811fa576e579673dff799dfc 100644
--- a/tests/src/Functional/RoleTest.php
+++ b/tests/src/Functional/RoleTest.php
@@ -21,7 +21,7 @@ class RoleTest extends RestrictByIPWebTestBase {
   /**
    * {@inheritdoc}
    */
-  public function setUp() {
+  public function setUp(): void {
     parent::setUp();
 
     // Create a role with administer permissions so we can load the user edit,
diff --git a/tests/src/Functional/UiTest.php b/tests/src/Functional/UiTest.php
index d2c8c067fd3d675f74d33a88506adf20cc130a85..c8d012e18f93b88494aaa0b5e07ab0b60c64992f 100644
--- a/tests/src/Functional/UiTest.php
+++ b/tests/src/Functional/UiTest.php
@@ -19,7 +19,7 @@ class UiTest extends RestrictByIPWebTestBase {
   /**
    * {@inheritdoc}
    */
-  public function setUp() {
+  public function setUp(): void {
     // Enable modules needed for these tests.
     parent::setUp();