From cedeedf7bb18ddb4ef436465c11a663634e6ddfc Mon Sep 17 00:00:00 2001
From: Tim van Dijen <tvdijen@gmail.com>
Date: Sat, 28 Aug 2021 10:54:28 +0200
Subject: [PATCH] Attempt for unit testing

---
 modules/saml/lib/Auth/Source/SP.php           | 24 +++++--
 tests/Utils/SpTester.php                      | 19 +++++-
 .../lib/Auth/Source/Auth_Source_SP_Test.php   | 64 +++++++++++++++++++
 3 files changed, 100 insertions(+), 7 deletions(-)

diff --git a/modules/saml/lib/Auth/Source/SP.php b/modules/saml/lib/Auth/Source/SP.php
index 95ac6c55f..e82405c4f 100644
--- a/modules/saml/lib/Auth/Source/SP.php
+++ b/modules/saml/lib/Auth/Source/SP.php
@@ -7,6 +7,7 @@ namespace SimpleSAML\Module\saml\Auth\Source;
 use SAML2\AuthnRequest;
 use SAML2\Binding;
 use SAML2\Constants;
+use SAML2\LogoutRequest;
 use SAML2\XML\saml\NameID;
 use SimpleSAML\Assert\Assert;
 use SimpleSAML\Auth;
@@ -614,7 +615,7 @@ class SP extends \SimpleSAML\Auth\Source
 
         $b = Binding::getBinding($dst['Binding']);
 
-        $this->sendSAML2AuthnRequest($state, $b, $ar);
+        $this->sendSAML2AuthnRequest($b, $ar);
 
         Assert::true(false);
     }
@@ -625,17 +626,31 @@ class SP extends \SimpleSAML\Auth\Source
      *
      * This function does not return.
      *
-     * @param array &$state  The state array.
      * @param \SAML2\Binding $binding  The binding.
      * @param \SAML2\AuthnRequest  $ar  The authentication request.
      */
-    public function sendSAML2AuthnRequest(array &$state, Binding $binding, AuthnRequest $ar): void
+    public function sendSAML2AuthnRequest(Binding $binding, AuthnRequest $ar): void
     {
         $binding->send($ar);
         Assert::true(false);
     }
 
 
+    /**
+     * Function to actually send the logout request.
+     *
+     * This function does not return.
+     *
+     * @param \SAML2\Binding $binding  The binding.
+     * @param \SAML2\LogoutRequest  $ar  The logout request.
+     */
+    public function sendSAML2LogoutRequest(Binding $binding, LogoutRequest $lr): void
+    {
+        $binding->send($lr);
+        Assert::true(false);
+    }
+
+
     /**
      * Send a SSO request to an IdP.
      *
@@ -992,9 +1007,8 @@ class SP extends \SimpleSAML\Auth\Source
         }
 
         $b = Binding::getBinding($endpoint['Binding']);
-        $b->send($lr);
 
-        Assert::true(false);
+        $this->sendSAML2LogoutRequest($b, $lr);
     }
 
 
diff --git a/tests/Utils/SpTester.php b/tests/Utils/SpTester.php
index a83396bbc..7f8d01884 100644
--- a/tests/Utils/SpTester.php
+++ b/tests/Utils/SpTester.php
@@ -7,6 +7,7 @@ namespace SimpleSAML\Test\Utils;
 use ReflectionObject;
 use SAML2\AuthnRequest;
 use SAML2\Binding;
+use SAML2\LogoutRequest;
 use SimpleSAML\Configuration;
 use SimpleSAML\Module\saml\Auth\Source\SP;
 
@@ -41,15 +42,29 @@ class SpTester extends SP
     /**
      * override the method that sends the request to avoid sending anything
      */
-    public function sendSAML2AuthnRequest(array &$state, Binding $binding, AuthnRequest $ar): void
+    public function sendSAML2AuthnRequest(Binding $binding, AuthnRequest $ar): void
     {
         // Exit test. Continuing would mean running into a assert(FALSE)
         throw new ExitTestException(
             [
-                'state'   => $state,
                 'binding' => $binding,
                 'ar'      => $ar,
             ]
         );
     }
+
+
+    /**
+     * override the method that sends the request to avoid sending anything
+     */
+    public function sendSAML2LogoutRequest(Binding $binding, LogoutRequest $lr): void
+    {
+        // Exit test. Continuing would mean running into a assert(FALSE)
+        throw new ExitTestException(
+            [
+                'binding' => $binding,
+                'lr'      => $lr,
+            ]
+        );
+    }
 }
diff --git a/tests/modules/saml/lib/Auth/Source/Auth_Source_SP_Test.php b/tests/modules/saml/lib/Auth/Source/Auth_Source_SP_Test.php
index 9c697ea1b..d748b61f6 100644
--- a/tests/modules/saml/lib/Auth/Source/Auth_Source_SP_Test.php
+++ b/tests/modules/saml/lib/Auth/Source/Auth_Source_SP_Test.php
@@ -120,6 +120,33 @@ class SPTest extends ClearStateTestCase
     }
 
 
+    /**
+     * Create a SAML LogoutRequest using \SimpleSAML\Module\saml\Auth\Source\SP
+     *
+     * @param array $state The state array to use in the test. This is an array of the parameters described in section
+     * 2 of https://simplesamlphp.org/docs/development/saml:sp
+     *
+     * @return \SAML2\LogoutRequest The LogoutRequest generated.
+     */
+    private function createLogoutRequest(array $state = []): LogoutRequest
+    {
+        $info = ['AuthId' => 'default-sp'];
+        $config = ['entityID' => 'https://engine.surfconext.nl/authentication/idp/metadata'];
+        $as = new SpTester($info, $config);
+
+        /** @var \SAML2\LogoutRequest $lr */
+        $lr = null;
+        try {
+            $as->startSLO2($state);
+            $this->assertTrue(false, 'Expected ExitTestException');
+        } catch (ExitTestException $e) {
+            $r = $e->getTestResult();
+            $lr = $r['lr'];
+        }
+        return $lr;
+    }
+
+
     /**
      * Test generating an AuthnRequest
      * @test
@@ -394,4 +421,41 @@ class SPTest extends ClearStateTestCase
         $as = new SpTester($info, $config);
         $as->authenticate($state);
     }
+
+
+    /**
+     * Test setting a logout-extension
+     */
+    public function testLogoutExtensions(): void
+    {
+        $entityId = "https://example.com";
+        $xml = MetaDataStorageSourceTest::generateIdpMetadataXml($entityId);
+        $c = [
+            'metadata.sources' => [
+                ["type" => "xml", "xml" => $xml],
+            ],
+        ];
+        Configuration::loadFromArray($c, '', 'simplesaml');
+
+        $state = [
+            'saml:logout:IdP' => 'https://engine.surfconext.nl/authentication/idp/metadata',
+            'saml:logout:NameID' => 'someone@example.com',
+            'saml:logout:SessionIndex' => 'abc123',
+            'saml:logout:Extensions' => [
+                'some extention'
+            ]
+        ];
+
+        $lr = $this->createLogoutRequest($state);
+
+        /** @var \SAML2\XML\samlp\Extensions $extentions */
+        $extensions = $lr->getExtensions();
+        $this->assertcount(1, $state['saml:logout:Extionsions']);
+
+        $xml = $lr->toSignedXML();
+
+        /** @var \DOMNode[] $q */
+        $q = Utils::xpQuery($xml, '/samlp:AuthnRequest/samlp:Extentions');
+        $this->assertCount(1, $q);
+    }
 }
-- 
GitLab