diff --git a/modules/admin/lib/Controller/Sandbox.php b/modules/admin/lib/Controller/Sandbox.php
new file mode 100644
index 0000000000000000000000000000000000000000..fc34d4cd839d4f24f49f04e187da61f0d5a6093a
--- /dev/null
+++ b/modules/admin/lib/Controller/Sandbox.php
@@ -0,0 +1,57 @@
+<?php
+
+declare(strict_types=1);
+
+namespace SimpleSAML\Module\admin\Controller;
+
+use SimpleSAML\Configuration;
+use SimpleSAML\Session;
+use SimpleSAML\XHTML\Template;
+
+/**
+ * Controller class for the admin module.
+ *
+ * This class serves the 'sandbox' views available in the module.
+ *
+ * @package SimpleSAML\Module\admin
+ */
+class Sandbox
+{
+    /** @var \SimpleSAML\Configuration */
+    protected Configuration $config;
+
+    /** @var \SimpleSAML\Session */
+    protected Session $session;
+
+
+    /**
+     * Sandbox constructor.
+     *
+     * @param \SimpleSAML\Configuration $config The configuration to use.
+     * @param \SimpleSAML\Session $session The current user session.
+     */
+    public function __construct(Configuration $config, Session $session)
+    {
+        $this->config = $config;
+        $this->session = $session;
+    }
+
+
+    /**
+     * Display the sandbox page
+     *
+     * @return \SimpleSAML\XHTML\Template
+     */
+    public function main(): Template
+    {
+        $template = new Template($this->config, 'sandbox.twig');
+        $template->data['pagetitle'] = 'Sandbox';
+        $template->data['sometext'] = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus.' .
+            ' Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit.' .
+            ' Donec et mollis dolor. Praesent et diam eget libero egestas mattis sit amet vitae augue. ' .
+            'Nam tincidunt congue enim, ut porta lorem lacinia consectetur.';
+        $template->data['remaining'] = $this->session->getAuthData('admin', 'Expire') - time();
+        $template->data['logout'] = null;
+        return $template;
+    }
+}
diff --git a/modules/admin/lib/Controller/Test.php b/modules/admin/lib/Controller/Test.php
index 334d027d9a426825fb201867fa9e09187e57aeab..36f3c3714bf59c47c09ea24e3218428b55675ed0 100644
--- a/modules/admin/lib/Controller/Test.php
+++ b/modules/admin/lib/Controller/Test.php
@@ -55,7 +55,7 @@ class Test
 
 
     /**
-     * ConfigController constructor.
+     * TestController constructor.
      *
      * @param \SimpleSAML\Configuration $config The configuration to use.
      * @param \SimpleSAML\Session $session The current user session.
@@ -109,7 +109,7 @@ class Test
      * @param string|null $as
      * @return \SimpleSAML\XHTML\Template|\SimpleSAML\HTTP\RunnableResponse
      */
-    public function main(Request $request, string $as = null)
+    public function main(Request $request, string $as = null): Response
     {
         $this->authUtils->requireAdmin();
         if (is_null($as)) {
diff --git a/modules/admin/routing/routes/routes.yml b/modules/admin/routing/routes/routes.yml
index 3cff6ed4c5fb4ec82a4e83a7d3c5df5bae7812fa..9fc4902bcd007624f3dcb45ab2e2603284d6e13b 100644
--- a/modules/admin/routing/routes/routes.yml
+++ b/modules/admin/routing/routes/routes.yml
@@ -7,6 +7,9 @@ admin-diagnostics:
 admin-phpinfo:
     path:       /phpinfo
     defaults:   { _controller: 'SimpleSAML\Module\admin\Controller\Config::phpinfo' }
+admin-sandbox:
+    path:       /sandbox
+    defaults:   { _controller: 'SimpleSAML\Module\admin\Controller\Sandbox::main' }
 admin-test:
     path:       /test/{as}
     defaults:   { _controller: 'SimpleSAML\Module\admin\Controller\Test::main', as: null }
diff --git a/routing/routes/routes.yml b/routing/routes/routes.yml
index bcc6ae92545bf279d382376795a1a9ab7825d0cb..cbfd6908c0acb0b2ad6788cf3b6bcd5a2b4b0e4a 100644
--- a/routing/routes/routes.yml
+++ b/routing/routes/routes.yml
@@ -27,3 +27,6 @@ websso-legacy-single-logout:
 websso-legacy-init-single-logout:
     path:       /saml2/idp/initSLO.php
     defaults:   { _controller: 'SimpleSAML\Module\saml\Controller\SingleLogout::initSingleLogout', path: /saml2/idp/initSingleLogout, permanent: true }
+admin-legacy:
+    path:       /admin
+    defaults:   { _controller: 'SimpleSAML\Module\admin\Controller\Config::main', path: /admin, permanent: true }
diff --git a/tests/modules/admin/lib/Controller/SandboxTest.php b/tests/modules/admin/lib/Controller/SandboxTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..c3246e851e15461a992c007368b4be92c1ed32a6
--- /dev/null
+++ b/tests/modules/admin/lib/Controller/SandboxTest.php
@@ -0,0 +1,56 @@
+<?php
+
+declare(strict_types=1);
+
+namespace SimpleSAML\Test\Module\admin\Controller;
+
+use PHPUnit\Framework\TestCase;
+use SimpleSAML\Configuration;
+use SimpleSAML\Module\admin\Controller;
+use SimpleSAML\Session;
+use SimpleSAML\XHTML\Template;
+
+/**
+ * Set of tests for the controllers in the "admin" module.
+ *
+ * @covers \SimpleSAML\Module\admin\Controller\Sandbox
+ * @package SimpleSAML\Test
+ */
+class SandboxTest extends TestCase
+{
+    /** @var \SimpleSAML\Configuration */
+    protected Configuration $config;
+
+    /** @var \SimpleSAML\Session */
+    protected Session $session;
+
+
+    /**
+     * Set up for each test.
+     */
+    protected function setUp(): void
+    {
+        parent::setUp();
+
+        $this->config = Configuration::loadFromArray(
+            [
+                'module.enable' => ['admin' => true],
+            ],
+            '[ARRAY]',
+            'simplesaml'
+        );
+
+        $this->session = Session::getSessionFromRequest();
+    }
+
+
+    /**
+     */
+    public function testSandbox(): void
+    {
+        $c = new Controller\Sandbox($this->config, $this->session);
+        $response = $c->main();
+
+        $this->assertInstanceOf(Template::class, $response);
+    }
+}
diff --git a/www/admin/index.php b/www/admin/index.php
deleted file mode 100644
index b77e3e4097cb7b21942baf87d1ef2693aa7c77da..0000000000000000000000000000000000000000
--- a/www/admin/index.php
+++ /dev/null
@@ -1,6 +0,0 @@
-<?php
-
-require_once('../_include.php');
-
-$httpUtils = new \SimpleSAML\Utils\HTTP();
-$httpUtils->redirectTrustedURL(\SimpleSAML\Module::getModuleURL('admin/'));
diff --git a/www/admin/sandbox.php b/www/admin/sandbox.php
deleted file mode 100644
index 07b3a245b1e996d6df599e4e08712894fabd089d..0000000000000000000000000000000000000000
--- a/www/admin/sandbox.php
+++ /dev/null
@@ -1,19 +0,0 @@
-<?php
-
-require_once('../_include.php');
-
-// Load SimpleSAMLphp configuration
-$config = \SimpleSAML\Configuration::getInstance()->toArray();
-$config = \SimpleSAML\Configuration::loadFromArray($config, '[ARRAY]', 'simplesaml');
-$session = \SimpleSAML\Session::getSessionFromRequest();
-
-$template = new \SimpleSAML\XHTML\Template($config, 'sandbox.twig');
-$template->data['pagetitle'] = 'Sandbox';
-$template->data['sometext'] = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus.' .
-    ' Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit.' .
-    ' Donec et mollis dolor. Praesent et diam eget libero egestas mattis sit amet vitae augue. ' .
-    'Nam tincidunt congue enim, ut porta lorem lacinia consectetur.';
-$template->data['remaining'] = $session->getAuthData('admin', 'Expire') - time();
-$template->data['logout'] = null;
-
-$template->send();