From 45dcbc2480d882f5394b2b090cff64ffbf4053e9 Mon Sep 17 00:00:00 2001
From: Jan-Hendrik Willms <tleilax+studip@gmail.com>
Date: Thu, 29 Aug 2024 14:48:53 +0000
Subject: [PATCH] Simple saml review

Merge request nod3zer0/stud-ip-siple-saml-php-plugin!1
---
 config/config_defaults.inc.php                |  16 +--
 .../auth_plugins/StudipAuthSimpleSamlPHP.php  | 111 ++++++++----------
 2 files changed, 59 insertions(+), 68 deletions(-)

diff --git a/config/config_defaults.inc.php b/config/config_defaults.inc.php
index 5b188622ee5..4a421f7fa55 100644
--- a/config/config_defaults.inc.php
+++ b/config/config_defaults.inc.php
@@ -326,13 +326,15 @@ $STUDIP_AUTH_CONFIG_OAUTH2 = [
     ],
 ];
 
-$STUDIP_AUTH_CONFIG_SIMPLESAMLPHP = array("reverse_proxy_url" => '',
-                                                "sp_name" => 'default-sp',
-                                                "user_data_mapping" =>      array(
-                                                "auth_user_md5.Email" => array("callback" => "getUserData", "map_args" => "email"),
-                                                "auth_user_md5.Nachname" => array("callback" => "getUserData", "map_args" => "firstName"),
-                                                "auth_user_md5.Vorname" => array("callback" => "getUserData", "map_args" => "lastName")));
-
+$STUDIP_AUTH_CONFIG_SIMPLESAMLPHP = [
+    'reverse_proxy_url' => '',
+    'sp_name'           => 'default-sp',
+    'user_data_mapping' => [
+        'auth_user_md5.Email'    => ['callback' => 'getUserData', 'map_args' => 'email'],
+        'auth_user_md5.Nachname' => ['callback' => 'getUserData', 'map_args' => 'firstName'],
+        'auth_user_md5.Vorname'  => ['callback' => 'getUserData', 'map_args' => 'lastName'],
+    ],
+];
 */
 
 //some additional authification-settings
diff --git a/lib/classes/auth_plugins/StudipAuthSimpleSamlPHP.php b/lib/classes/auth_plugins/StudipAuthSimpleSamlPHP.php
index 469fe155576..163465b311b 100644
--- a/lib/classes/auth_plugins/StudipAuthSimpleSamlPHP.php
+++ b/lib/classes/auth_plugins/StudipAuthSimpleSamlPHP.php
@@ -5,21 +5,22 @@
  * author: Rene Ceska <ceskar2001@gmail.com>
  * This class is used to authenticate users through SimpleSAMLphp.
  * This code was inspired by other Stud.IP auth plugins.
+ *
+ * @since Stud.IP 6.0
  */
-
-// Default location of SimpleSamlPHP _autoload. Change if needed.
-require_once('/var/simplesamlphp/src/_autoload.php');
-
 class StudipAuthSimpleSamlPHP extends StudipAuthSSO
 {
     // Reverse proxy domain
-    public $reverse_proxy_url;
+    public ?string $reverse_proxy_url = null;
+
     // Name of the SimpleSAMLphp SP
-    public $sp_name;
+    public string $sp_name;
+
     // Name of attribute that contains username (if empty it will use NameID as username)
-    public $username_attribute;
-    public $userdata;
-    public $as;
+    public ?string $username_attribute = null;
+
+    public ?array $userdata = null;
+    public SimpleSAML\Auth\Simple $as;
 
     /**
      * Constructor: read auth information from remote SP.
@@ -27,44 +28,17 @@ class StudipAuthSimpleSamlPHP extends StudipAuthSSO
     public function __construct($config = [])
     {
         parent::__construct($config);
-        // check if user chosen to login through this plugin
-        if (Request::get('sso') === $this->plugin_name) {
-
-            $this->as = new \SimpleSAML\Auth\Simple($this->sp_name);
-
-
-            //return to right url, otherwise stud.ip will break
-            if(empty($this->reverse_proxy_url)){
-                $return_to_url = (empty($_SERVER['HTTPS']) ? 'http' : 'https') . "://$_SERVER[HTTP_HOST]"."/dispatch.php/start?again=yes&sso=simplesamlphp&cancel_login=1";
-            }else{
-                $return_to_url =  $this->reverse_proxy_url . "/dispatch.php/start?again=yes&sso=simplesamlphp&cancel_login=1";
-            }
-
-
-            // check if user is already authenticated and if not, authenticate them
-            if (!$this->as->isAuthenticated()) {
-                $this->as->requireAuth(['ReturnTo' => $return_to_url]);
-            }
-            $this->userdata = [];
-            // get username
-            if (empty($username_attribute)){
-                    $this->userdata['username'] =  $this->as->getAuthData('saml:sp:NameID')->getValue();
-            }else{
-                    $this->userdata['username'] =  $this->as->getAttributes()[$this->username_attribute];
-            }
-            // get other user attributes
-            $this->userdata = array_merge($this->userdata, $this->as->getAttributes());
-
-            // cleanup session so it does not interfere with Stud.IP session
-            $session = \SimpleSAML\Session::getSessionFromRequest();
-            $session->cleanup();
-        }
 
         if (!isset($this->plugin_fullname)) {
-            $this->plugin_fullname = _('Federated');
+            $this->plugin_fullname = _('SAML');
         }
         if (!isset($this->login_description)) {
-            $this->login_description = _('Login trough your institution');
+            $this->login_description = _('für Single Sign On mit SAML');
+        }
+
+        // check if user chosen to login through this plugin
+        if (Request::get('sso') === $this->plugin_name) {
+            $this->as = new SimpleSAML\Auth\Simple($this->sp_name);
         }
     }
 
@@ -73,7 +47,7 @@ class StudipAuthSimpleSamlPHP extends StudipAuthSSO
      */
     public function getUser()
     {
-        return $this->userdata['username'];
+        return $this->getUserData('username');
     }
 
     /**
@@ -87,38 +61,37 @@ class StudipAuthSimpleSamlPHP extends StudipAuthSSO
             return $this->getUser();
         }
 
-        //return to right url, otherwise stud.ip will break
-        if(empty($this->reverse_proxy_url)){
-            $return_to_url = (empty($_SERVER['HTTPS']) ? 'http' : 'https') . "://$_SERVER[HTTP_HOST]"."/dispatch.php/start?again=yes&sso=simplesamlphp&cancel_login=1";
-        }else{
-            $return_to_url =  $this->reverse_proxy_url . "/dispatch.php/start?again=yes&sso=simplesamlphp&cancel_login=1";
-        }
-
-
         // check if user is already authenticated and if not, authenticate them
         if (!$this->as->isAuthenticated()) {
-            $this->as->requireAuth(['ReturnTo' => $return_to_url]);
+            $this->as->requireAuth(['ReturnTo' => $this->getReturnToURL()]);
         }
 
-        if (empty($username_attribute)){
-                $this->userdata['username'] =  $this->as->getAuthData('saml:sp:NameID')->getValue();
-        }else{
-                $this->userdata['username'] =  $this->as->getAttributes()[$this->username_attribute];
+        $this->userdata = [];
+
+        // get username
+        if (empty($this->username_attribute)) {
+            $this->userdata['username'] =  $this->as->getAuthData('saml:sp:NameID')->getValue();
+        } else {
+            $this->userdata['username'] =  $this->as->getAttributes()[$this->username_attribute];
         }
-        $session = \SimpleSAML\Session::getSessionFromRequest();
-        $session->cleanup();
+
+        // get other user attributes
+        $this->userdata = array_merge($this->userdata, $this->as->getAttributes());
+
+        // cleanup session so it does not interfere with Stud.IP session
+        SimpleSAML\Session::getSessionFromRequest()->cleanup();
+
         return $this->getUser();
     }
 
     /**
      * Callback that can be used in user_data_mapping array.
      */
-    function getUserData($key)
+    public function getUserData($key)
     {
         return $this->userdata[$key];
     }
 
-
     /**
      * Logout the user.
      */
@@ -127,4 +100,20 @@ class StudipAuthSimpleSamlPHP extends StudipAuthSSO
         $auth = new \SimpleSAML\Auth\Simple($this->sp_name);
         $auth->Logout();
     }
+
+    /**
+     * Returns the required return to url
+     */
+    public function getReturnToURL(): string
+    {
+        $old_base = URLHelper::setBaseURL($this->reverse_proxy_url ?: $GLOBALS['ABSOLUTE_URI_STUDIP']);
+        $return_to_url = URLHelper::getURL('dispatch.php/start', [
+            'again'        => 'yes',
+            'cancel_login' => 1,
+            'sso'          => $this->plugin_name,
+        ]);
+        URLHelper::setBaseURL($old_base);
+
+        return $return_to_url;
+    }
 }
-- 
GitLab